js:
/**
 * 更新说明：
 * 20231218
 * 1 单仓操作中修改了spider点击动作，是网络文件时，跳转到spider子页
 * 2 修改getfilename函数，当参数有？时取前面作为取文件名的基础
 * 3 修改了操作spider函数，添加判断本地仓库还是网络仓库。文件下载完毕后修改本地其他仓库spider
 * 4 添加了一个采集分析函数，没写完
 */


/**
 * mybox 初始化
 *  config.新函数:'file:///storage/emulated/0/Pictures/新函数.js';
    //mybox仓库文件的真实路径
    config.boxpath = "file:///storage/emulated/0/mybox/";
    //插件历史记录的保存路径
    config.lishi = myconfig.boxpath+"历史.json";
    //本地仓文件
    config.dancang = myconfig.boxpath+'本地单仓.json';
    config.duocang=myconfig.boxpath+'本地多仓.json';
    config.caiji = myconfig.boxpath+'采集站.json';
    config.shoucang = myconfig.boxpath+'收藏.json';
    

 */


function mybox初始化() {
    if (!fileExist(config.boxpath)) {
        makedir(config.boxpath)
        makedir(config.jarpath)
        makedir(config.jspath)
        makedir(config.jsonpath)
        makedir(config.otherpath)
        if (!fileExist(config.dancang)) {
            var bdc = {}
            var shuoming = "由海阔TVBOX插件编辑生成！"
            var spider = ""
            var wallpaper = ""
            var warningText = "接口免费整理维护，请勿付费购买"
            var sites = []
            var parses = []
            var rules = []
            var lives = []
            var flags = []
            var ads = []
            var doh = []
            var ijk = []

            bdc.shuoming = shuoming
            bdc.spider = spider
            bdc.wallpaper = wallpaper
            bdc.warningText = warningText
            bdc.sites = sites
            bdc.parses = parses
            bdc.rules = rules
            bdc.lives = lives
            bdc.flags = flags
            bdc.ads = ads
            bdc.doh = doh
            bdc.ijk = ijk
            writeFile(config.dancang, JSON.stringify(bdc))

        }
        //判断历史文件是否存在，历史文件是指收集过的网络仓库地址
        //使用url做键名防止重复 用网站名当键值
        if (!fileExist(config.lishi)) {
            writeFile(config.lishi, "[]")
        }

        if (!fileExist(config.shoucang)) {
            writeFile(config.shoucang, "{}")
        }
        if (!fileExist(config.shuoming)) {
            writeFile(config.shuoming, "")
        }

        if (!fileExist(config.caiji)) {
            var cj = {
                gzsm: ['首页推荐规则', '栏目列表规则', '影片列表规则', '影片详情规则', '影片播放规则'],
                gz_app: [],
                gz_xmlapp: [],
                gz_ac: [],
                gz_xmlac: [],
                app: {},
                //nav?token=
                xml_app: {},
                ac: {},
                //?ac=list
                xml_ac: {}
                //?ac=list 返回的是xml
            }
            writeFile(config.caiji, JSON.stringify(cj))
        }
    }
}
/**
 * 全局变量
 */
//给按钮用  取消加载框等
var nono = '#noRecordHistory##noHistory##noLoading#'
var headerok312 = { 'User-Agent': 'okhttp/3.12.11' }
/**
 * 界面函数
 */
function 采集站分析(){
    var d=[]
    var cj=[]
    dd(d, 'input', '历史', '输入网址或文件地址', '', $.toString(() => {
        putMyVar("wangzhi", input);
        return 'hiker://page/历史'
    }), {
        defaultValue: getMyVar('wangzhi', ''),
        onChange: "putMyVar('wangzhi', input)"
    })
    dd(d, 't2', '使用ac读栏目', '', '', $().lazyRule(()=>{
        putMyVar('todo','ac1')
        refreshPage()
        return 'toast://ac1'
    }))
    dd(d, 't2', '使用nav读栏目', '', '', $().lazyRule(()=>{
        putMyVar('todo','nav1')
        refreshPage()
        return 'toast://nav1'
    }))
    var todo=getMyVar('todo','')
    if(todo!=''){
        var url=getMyVar('wangzhi')
        var flg=0
        switch (todo){
            case 'ac1':
                var h=fetch(url+'?ac=list')
                putMyVar('jia1','?ac=list')
                if(h.indexOf('xml')!=-1){
                    //是xml
                    flg=2
                }else{
                    var rjson=strTojson(h)
                    if(rjson.err='ok'){
                        var json=rjson.json
                        flg=1
                    }else{
                        log(rjson.message)
                        toast('文件解析错误')
                    }
                }
                
                break;
            case 'nav1':
                var h=fetch(url+'nav?token=')
                putMyVar('jia1','nav?token=')
                if(h.indexOf('xml')!=-1){
                    //是xml
                    flg=2
                }else{
                var rjson=strTojson(h)
                    if(rjson.err='ok'){
                        var json=rjson.json
                        flg=1
                    }else{
                        log(rjson.message)
                        toast('文件解析错误')
                    }
                }
                break;
            case 'ac2':
                var h=fetch(url+'?ac=videolist&t='+getMyVar('typeid'))
                putMyVar('jia2','?ac=videolist&t=')
                if(h.indexOf('xml')!=-1){
                    //是xml
                    flg=4
                }else{
                    var rjson=strTojson(h)
                    if(rjson.err='ok'){
                        var json=rjson.json
                        flg=3
                    }else{
                        log(rjson.message)
                        toast('文件解析错误')
                    }
                }
                
                break;
            case 'ac3':
                var h=fetch(url+'?ac=videolist&ids='+getMyVar('videoid'))
                putMyVar('jia3','?ac=videolist&ids=')
                if(h.indexOf('xml')!=-1){
                    //是xml
                    flg=6
                }else{
                    var rjson=strTojson(h)
                    if(rjson.err='ok'){
                        var json=rjson.json
                        flg=5
                    }else{
                        log(rjson.message)
                        toast('文件解析错误')
                    }
                }
                
                break;
        }

        if(flg===1){
            var keys=Object.keys(json)
            dd(d,'tc','得到键'+keys.length+'个',keys)
            for(let i=0;i<keys.length;i++){
                dd(d,'t1',keys[i],json[keys[i]])
            }
        }
        if(flg===2){
            var list=pdfa(h,'class&&ty')
            dd(d,'tc','得到键'+list.length+'个',list)
            for(let i=0;i<list.length;i++){
                dd(d,'t1',pdfh(list[i],'ty&&Text'),pdfh(list[i],'ty&&id'),'',$().lazyRule((typeid)=>{
                    putMyVar('todo','ac2')
                    putMyVar('typeid',typeid)
                    refreshPage()
                    return 'toast://ac2'
                },pdfh(list[i],'ty&&id')))
            }
        }
        if(flg===4){
            var list=pdfa(h,'list&&video')
            dd(d,'tc','得到键'+list.length+'个',list)
            for(let i=0;i<list.length;i++){
                dd(d,'movie_3',pdfh(list[i],'name&&Text'),pdfh(list[i],'id&&Text'),pdfh(list[i],'pic&&Text'),$().lazyRule((videoid)=>{
                    putMyVar('todo','ac3')
                    putMyVar('videoid',videoid)
                    refreshPage()
                    return 'toast://ac3'
                },pdfh(list[i],'id&&Text')))
            }
        }
        if(flg===6){
            dd(d,'pic_1',pdfh(h,'name&&Text'),pdfh(h,'area&&Text'),pdfh(h,'pic&&Text'))
            dd(d,'t1','未处理连接',pdfh(h,'dl&&Text'),'',pdfh(h,'dl&&Text'))
            dd(d,'tc','点这里保存采集站',getMyVar('jia1')+';'+getMyVar('jia2')+';'+getMyVar('jia3'))

        }
        clearMyVar('todo')
    }
    setResult(d)
}
function mybox显示首页() {
    dd(d, 'tc', 'MyBox 助手', '我要做tvbox的全能助手')
    dd(d, 'l')
    dd(d, 't2', '在线仓库浏览', '', '', 'hiker://page/在线仓库浏览')
    dd(d, 't2', '本地仓库操作', '', '', 'hiker://page/本地仓库操作')
    dd(d, 't2', '文件管理', '', '', 'hiker://page/文件管理')
    dd(d, 't2', '说明文档', '', '', 'editFile://' + config.shuoming)
    dd(d, 'l')
    dd(d, 'tc', '【 在 线 工 具 】')
    dd(d, 't2', '🔥黎歌の主页', '', '', 'https://www.lige.fit/', { newWindow: true });
    dd(d, 't2', '🔥香雅晴主页', '', '', 'https://www.123pan.com/s/alSeVv-lGO0A.html', { newWindow: true });
    dd(d, 't2', '🔥海阔视界下载', '', '', 'https://www.123pan.com/s/fajA-YlLQh', { newWindow: true });
    dd(d, 't2', '👍base64编码', '', '', 'https://tool.ip138.com/base64/', { newWindow: true })
    dd(d, 't2', '👍JSON工具', '', '', 'https://www.toolnb.com/tools/json.html', { newWindow: true })
    dd(d, 'l')
    dd(d, 'tc', '【 实 用 小 程 序 】')
    dd(d, 't2', '🔥网站调试助手', '', '', 'hiker://debug');
    dd(d, 't2', '🔥XYQ推送', '', '', 'hiker://home@XYQ推送');
    dd(d, 't2', '🔥香情影视', '', '', 'hiker://home@香情影视');
    dd(d, 't2', '🔥MY阿里云盘', '', '', 'hiker://home@MY阿里云盘');
    dd(d, 't2', '🔥云盘君(推送)', '', '', 'hiker://home@云盘君(推送)');
    dd(d, 't2', '🔥影视仓推送', '', '', 'hiker://home@影视仓推送');
    //dd(d, 't2', '🔥XYQ推送', '', '', 'hiker://home@香情影视');
    //dd(d, 't2', '🔥XYQ推送', '', '', 'hiker://home@香情影视');

    
    
    dd(d,'t2','二级页测试','','',$().rule((c)=>{
        log($.hiker.nono)
        setResult(JSON.parse(c))
    },JSON.stringify([{
        col_type:'text_1',
        title:'这里是第二页',
        desc:nono
    }])))


}
function mybox显示在线仓库浏览() {
    dd(d, 'input', '历史', '输入网址或文件地址', '', $.toString(() => {
        putMyVar("wangzhi", input);
        return 'hiker://page/历史'
    }), {
        defaultValue: getMyVar('wangzhi', ''),
        onChange: "putMyVar('wangzhi', input)"
    })

    dd(d, 't2', 'API下载仓库', '', '', ttapi)

    var tt = $("", "输入仓库说明文字").input((nowtime) => {
        try {
            var file = getMyVar('wangzhi')
            if (file.startsWith('http')) {
                var h = fetch(file, {
                    headers: { 'User-Agent': 'okhttp/3.12.11' }
                })
                var filename = file.substring(file.lastIndexOf('/') + 1)
                var sm = {}
                sm.wangzhi = file
                sm.shuoming = input
                if(fileExist(config.boxpath + filename)){
                    writeFile(config.boxpath + nowtime+filename, h)
                    writeFile(config.boxpath + nowtime+filename + '.说明', JSON.stringify(sm))
                }else{
                    writeFile(config.boxpath + filename, h)
                    writeFile(config.boxpath + filename + '.说明', JSON.stringify(sm))
                }
                refreshPage()
                return 'toast://仓库下载完成'
            } else {
                return 'toast://网址需要HTTP开头'
            }
        } catch (e) {
            log('在线仓库浏览页---文件下载错误')
            log(e.message)
        }
        return "toast://下载文件错误"
    },getnowtime())
    var ttapi = $("", "输入仓库说明文字").input((nowtime) => {
        try {
            var file = getMyVar('wangzhi')
            if (file.startsWith('http')) {
                var h = fetch('http://api.lige.fit/ua', {
                    headers: {
                        'content-type': 'application/json'
                    },
                    body: {
                        'url': file
                    },
                    method: 'POST'
                })
                var filename = file.substring(file.lastIndexOf('/') + 1)
                var sm = {}
                sm.wangzhi = file
                sm.shuoming = input
                if(fileExist(config.boxpath + filename)){
                    writeFile(config.boxpath + nowtime+filename, h)
                    writeFile(config.boxpath + nowtime+filename + '.说明', JSON.stringify(sm))
                }else{
                    writeFile(config.boxpath + filename, h)
                    writeFile(config.boxpath + filename + '.说明', JSON.stringify(sm))
                }
                refreshPage()
                return 'toast://仓库下载完成'
            } else {
                return 'toast://网址需要HTTP开头'
            }
        } catch (e) {
            log('在线仓库浏览页---文件下载错误')
            log(e.message)
        }
        return "toast://下载文件错误"
    },getnowtime())

    dd(d, 't2', '下载仓库', '', '', tt)
    dd(d, 't2', 'API下载仓库', '', '', ttapi)
    dd(d, 't2', '操作spider', '', '', 'hiker://page/spider',{file:getMyVar('wangzhi')})
    dd(d, 't2', '操作sites', '', '','hiker://page/sites',{file:getMyVar('wangzhi')})
    dd(d, 't2', '操作parses', '', '', 'hiker://page/parses',{file:getMyVar('wangzhi')})
    dd(d, 't2', '查看源码', '', '', 'hiker://page/源码', { wangzhi: getMyVar('wangzhi'),wztype:'直接' })
    dd(d, 't2', 'API查看源码', '', '', 'hiker://page/源码', { wangzhi: getMyVar('wangzhi') ,wztype:'api'})
    //dd(d, 't2', '仓库本地化', '', '', 'hiker://page/仓库本地化', { wangzhi: getMyVar('wangzhi') })
    dd(d, 'l')
    //显示目录下文件，不能操作
    var files = getfiles(config.boxpath)
    for (let i = 0; i < files.filearr.length; i++) {
        dd(d, 't1', files.filearr[i], '', '', 'editFile://' + config.boxpath + files.filearr[i])
    }
}
function mybox显示本地仓库操作(){
    dd(d,'t1','本地单仓操作：',config.dancang,'','hiker://page/单仓操作')
    dd(d,'t1','本地多仓操作：',config.duocang,'','hiker://page/多仓操作')
    dd(d, 't2', '编辑单仓源码', '', '', 'editFile://' + config.dancang)
    dd(d, 't2', '编辑多仓源码', '', '', 'editFile://' + config.duocang)
    dd(d, 't2', '重建仓源码', '', '', 新建本地仓)
    dd(d, 't2', '其他本地仓操作', '', '','hiker://page/文件管理')
    dd(d,'l')
        //显示目录下文件，不能操作
        var files = getfiles(config.boxpath)
        for (let i = 0; i < files.filearr.length; i++) {
            dd(d, 't1', files.filearr[i], '', '', 'editFile://' + config.boxpath + files.filearr[i])
        }

}
function mybox单仓操作(){
//本地单仓操作
//其他本地仓操作
    var file = MY_PARAMS.file || getParam('file')   
    try{
        if(file){
            //传入file参数 file开头  caln开头 
            if(file.startsWith('file://')){
                var json=JSON.parse(fetch(file))
            }else{
                // 注意 这里可能会发生错误
                var rp='clan://localhost/mybox/'
                var json=JSON.parse(fetch(config.boxpath+file.replace(rp,'')))
            }
            
        }else{
            //没传入file参数 就直接操作本地单仓
            var json=JSON.parse(fetch(config.dancang))
            file=config.dancang
        }
        var keys=Object.keys(json)
        //不输入了  跳转到JAR更换页
        /*
        var tt = $("./jar/xxx.jar", "输入JAR相对路径").input(() => {
            var json1=JSON.parse(fetch(config.dancang))
            json1.spider=input
            writeFile(config.dancang,JSON.stringify(json1))
            refreshPage()
            return 'toast://JAR更换结束'
        })
        */
        
        for(let i=0;i<keys.length;i++){
            switch (keys[i]){
                case 'spider':
                    if(json.spider.startsWith('http')){
                        dd(d,'t1','spider 是网络文件需要下载：',json.spider,'','hiker://page/spider',{file:file,item:json.spider})
                    }else{
                        dd(d,'t1','spider 本地单仓JAR(点击更换)：',json.spider,'','hiker://page/更换jar')
                    }
                    
                    break;
                case 'sites':
                    dd(d,'t1','sites 网站接口：',json.sites,'','hiker://page/sites',{file:file})
                    break;
                default:
                    dd(d,'t1',keys[i],json[keys[i]])
            }
        }
    }catch(e){
        log('单仓操作错误')
        log(e.message)
    }
}
function mybox多仓操作(){

    var d=[];
    dd(d,'s','追加黎歌仓库','','',$('#noLoading#').lazyRule(() => {
        var lg=eval(fetch('https://api.lige.fit/getJson'))
        //log(lg[1].url)
        var json=JSON.parse(fetch(config.duocang))
        var k=json.urls
        var yiyou=[]
        for(let i=0;i<k.length;i++){
            yiyou.push(k[i].url)
        }
        for(let i=0;i<lg.length;i++){
            if(!yiyou.includes(lg[i].url)){
                //本地多仓内没有连接
                json.urls.push(lg[i])
            }
        }
        writeFile(config.duocang,JSON.stringify(json))
        refreshPage()
        return 'toast://添加结束'
    }))
    try{
        if(!fileExist(config.duocang)){
            var duo={urls:[]}
            duo.urls.push({url:'clan://localhost/mybox/本地单仓.json',name:'本地单仓'})
            writeFile(config.duocang,JSON.stringify(duo))
        }
        var json=JSON.parse(fetch(config.duocang))
        var k=json.urls
        dd(d,'tc','【 本 地 多 仓 接 口 列 表 】')
        dd(d,'l')
        for(let ii=0;ii<k.length;ii++){
            let longclick = []
            longclick.push({
                title: '删除',
                js: $.toString((ii) => {
                        let j = JSON.parse(fetch(config.duocang));
                        j.urls.splice(ii, 1)
                        writeFile(config.duocang, JSON.stringify(j));
                        refreshPage()
                        return 'hiker://empty'
                }, ii)
            })
            if(k[ii].url.startsWith('clan')){
                dd(d,'t1',k[ii].name, k[ii].url,'','hiker://page/单仓操作',{file:k[ii].url,})
            }else{
                dd(d,'t1',k[ii].name, k[ii].url)
            }
            
        }

    }catch(e){
        log('多仓操作错误')
        log(e.message)
    }
    setResult(d);
}
function mybox更换jar(){
    dd(d,'tc','【 点击更换本地单仓spider 】')
    var files=getfiles(config.boxpath+'jar/')
    for(let i=0;i<files.filearr.length;i++){
        let tt=$('#noLoading#').lazyRule((f) => {
            let bddc=JSON.parse(fetch(config.dancang));
            bddc.spider='./jar/'+f;
            writeFile(config.dancang,JSON.stringify(bddc));
            back();
            return 'toast://本地单仓spider设置成功';
        },files.filearr[i])
        if(!files.filearr[i].endsWith('.说明')){
            if(fileExist(config.boxpath+'jar/'+files.filearr[i]+'.说明')){
                let sm=JSON.parse(fetch(config.boxpath+'jar/'+files.filearr[i]+'.说明'))
                dd(d,'t1',files.filearr[i],sm.shuoming,'',tt);
            }else{
                dd(d,'t1',files.filearr[i],'无说明文件','',tt);
            }
        }
        
        
    }
}
function 文件选择二级页(path){
    //这是一个二级页模板
    //给我一个目录
    //返回一个文件列表
    //点击列表的时候执行一段JS
    var rjson=getfiles(path)
    var d=[]
    if(rjson.err=='ok'){
        let files=rjson.filearr
        for(let i=0;i<files.length;i++){
            let myjs=$('#noLoading#').lazyRule((i) => {
                putMyVar('todo','点击');
                putMyVar('val',i);
                refreshPage(false);
                return 'toast://你点击了第'+i+'个按钮'
            },i)
            d.push({col_type:'text_1',title:files[i],url:myjs})
        }
    }
    if(getMyVar('todo')=='点击'){
        let val=getMyVar('val')
        toast('在刷新前你点击了第'+val+'个按钮')
        clearMyVar('todo')
        clearMyVar('val')
    }
    setResult(d)
}
function 显示目录中文件() {
    var mypath = MY_PARAMS.mypath || config.boxpath
    //var files=getfiles(mypath)
    //files:{base:当前目录,patharr:[],filearr:[]}
    var d = []
    //log('显示目录中文件-f:' + f)
    var files = getfiles(mypath)
    //log(files)
    dd(d, 'tc', '[ 当前目录 ]', files.base)
    var parentpath = getparent(files.base)
    dd(d, 't1', '< .. >', '', '', 'hiker://page/文件管理', { mypath: parentpath })
    //显示子目录
    var pa = files.patharr
    //注意 files.base 结尾没有'/'
    for (let i = 0; i < pa.length; i++) {
        dd(d, 't1', '< ' + pa[i] + ' >', '', '', 'hiker://page/文件管理', { mypath: files.base + pa[i] + '/' })
    }
    var fa = files.filearr
    for (let i = 0; i < fa.length; i++) {
        let jjss = $.toString((fpath, fname) => {
            if (input == "删除") {
                var file_path = fpath + fname;
                var file = new java.io.File(file_path);
                file.delete();
                toast("删除成功！");
            }
            if (input == "编辑源码") {
                return 'editFile://file://' + fpath + fname;
            }
            if (input == "json查看") {
                return 'hiker://page/通用json?file=file://' + fpath + fname;
            }
            if (input == "复制地址") {
                return 'copy://file://' + fpath + fname;
            }
            if (input == "复制相对地址") {
                fpath=fpath.replace('/storage/emulated/0/mybox/','')
                return 'copy://./' + fpath + fname;
            }
            if (input == "复制CLAN地址") {
                fpath=fpath.replace('/storage/emulated/0/','')
                return 'copy://clan://localhost/' + fpath + fname;
            }
            if (input == "其他本地仓") {
                return 'hiker://page/单仓操作?file=file://' + fpath + fname;
            }
        }, files.base, fa[i])

        var s = {};
        s.title = "选择";
        s.options = ["json查看", "其他本地仓","删除", "编辑源码", "复制地址", "复制相对地址","复制CLAN地址"];
        s.col = 2;
        s.js = jjss;
        var 选择 = $.stringify(s);

        dd(d, 't1', fa[i], '', '', 'select://' + 选择)
    }

    setResult(d)
}
function 操作spider(){
    var now=getnowtime()
    var d=[]
    var file=MY_PARAMS.file  || getParam('file','')
    var item=MY_PARAMS.item || getParam('item','')
    if(file.startsWith('file')){
        //是从本地其他库过来的  不知道源仓库地址
        var h=fetch(file)
        var rjson = strTojson(h)
    }else{
        //file 是仓库地址  item 是 spider值
        var h = 取仓库源码(file,'api')
        var rjson = strTojson(h)
        item = rjson.json.spider
    }

    var md5file=config.boxpath+'已有文件md5.json'
    //item 是本仓库 jar 文件的完整路径 带MD5
    var item_url = item.split(';')[0]
    var item_filename = getfilename(item_url)
    var ymd5 = ''
    if (item.indexOf(';md5;') != -1) {
        ymd5 = item.split(';md5;')[1]
    }
    if (item == '') {
        toast('获取文件名错误');
        log('获取文件名错误: ' + item);
        back();
    }
if(item_url.startsWith('./')){
    if(file.startsWith('file')){
        
        toast('仓库使用相对地址，无法下载！')
        back();
        return
    }else{
        item_url=getfilepath(file)+item_url
    }
    
}
//功能开始
//log('filetype' + filetype)
var jarpath = config.boxpath + 'jar/'
if (!fileExist(jarpath)) {
        makedir(jarpath.replace('file://'))
    }
if (!fileExist(md5file)) {
    writeFile(md5file,'{}')
}
var mymd5=JSON.parse(fetch(md5file))
var md5list=Object.keys(mymd5)
if(md5list.includes(ymd5) && ymd5!=''){
    dd(d,'tc','已经下载过相同MD5的文件',mymd5[ymd5])
    if(fileExist(jarpath + mymd5[ymd5] + '.说明')){
        let sm = JSON.parse(fetch(jarpath + mymd5[ymd5] + '.说明'))
        dd(d, 't1', '本地文件说明: ', sm.shuoming)
        dd(d, 't1', '本地文件所属源仓库: ', sm.cangku)
        dd(d, 't1', '本地文件源地址: ', sm.wangzhi)
    }
}else if (fileExist(jarpath + item_filename)) {
    //本地存在同名文件 显示相关信息
    if (ymd5 != '') {
        //网络文件有MD5 显示MD5对比
        dd(d, 'text_center_1', '本地有同名文件 MD5对比', ymd5 + '\n' + md5(jarpath + item_filename))
    }
    if (fileExist(jarpath + item_filename + '.说明')) {
        //本地文件有没有说明文件
        let sm = JSON.parse(fetch(jarpath + item_filename + '.说明'))
        log('本地文件说明：')
        log(sm)
        dd(d, 't1', '本地文件说明: ', sm.shuoming)
        dd(d, 't1', '本地文件所属源仓库: ', sm.cangku)
        dd(d, 't1', '本地文件源地址: ', sm.wangzhi)
    }
}
d.push({
    title: '说明',
    desc: '下载文件的说明内容',
    col_type: 'input',
    url: $.toString(() => {
        putMyVar('shuoming', input);
        refreshPage();
        return 'hiker://empty'
    }),
    extra: {
        defaultValue: getMyVar('shuoming', ''),
        onChange: "putMyVar('shuoming', input)"
    }
});

//功能按钮
var 下载按钮 = $().lazyRule((url) => {
    putMyVar('todo', '下载')
    //putMyVar('item_url',url)
    refreshPage()
    return 'hiker://empty'
}, item_url)
//dd(d, 't1', '点击下载', '', '', 'hiker://page/文件下载?file=' + item_url)
dd(d, 't1', '点击下载JAR', '', '', 下载按钮);

var 添加到本地单仓 = $().lazyRule((fn,item) => {
    var h=JSON.parse(fetch(config.dancang))
    if(fileExist(config.boxpath+'jar/'+fn)){
        h.spider='./jar/'+fn
    }else{
        h.spider=item
    }
    writeFile(config.dancang,JSON.stringify(h))
    return 'toast://已经添加到本地单仓'
}, item_filename,item)
dd(d, 't1', '添加到本地单仓', '', '', 添加到本地单仓);

if (getMyVar('todo', '') === '下载') {
    //下载文件
    log('jar 文件下载地址: '+item_url)
    var h = fetch(item_url, {
        toHex: true
    })
    var shuoming = getMyVar('shuoming', '')
    var sm = {}
    sm.shuoming = shuoming
    sm.cangku = file
    sm.wangzhi = item
    if (fileExist(jarpath + item_filename)) {
        writeHexFile(jarpath + now + item_filename, h)
        writeFile(jarpath + now + item_filename + '.说明', JSON.stringify(sm))
        var jarmd5=JSON.parse(fetch(config.boxpath+'已有文件md5.json'))
        jarmd5[ymd5]=now +item_filename
        writeFile(config.boxpath+'已有文件md5.json',JSON.stringify(jarmd5))
    } else {
        writeHexFile(jarpath + item_filename, h)
        writeFile(jarpath + item_filename + '.说明', JSON.stringify(sm))
        var jarmd5=JSON.parse(fetch(config.boxpath+'已有文件md5.json'))
        jarmd5[ymd5]=item_filename
        writeFile(config.boxpath+'已有文件md5.json',JSON.stringify(jarmd5))
    }
    clearMyVar('shuoming');
    clearMyVar('todo');
    toast('文件下载完成，请刷新！');
    dd(d, 'text_center_1', '文件下载完成：', jarpath + item_filename);
    //判断文件是否下好，修改本地其他仓库spider
    if(fileExist(jarpath + item_filename)){
        rjson.json.spider='./jar/' + item_filename
        writeFile(file,JSON.stringify(rjson.json))
    }
}
setResult(d)
}
function 操作parses(){
    if(file.startsWith('http')){
        var h = 取仓库源码(file,'api')
        var httpfg=true
    }else{
        var h = fetch(file)
        var httpfg=false
    }
    var rjson = strTojson(h)
    if(rjson.err=='ok'){
        var item = rjson.json.parses
        //显示的内容是 文件 file 中 sites 键下的内容
        dd(d,'tc','【 点我追加所有到本地单仓 】','','',$('#noLoading#').lazyRule((item) => {
            var h=fetch(config.dancang)
            var bddc=JSON.parse(h)
            for(let i=0;i<item.length;i++){
                if(h.indexOf(JSON.stringify(item[i]))!=-1){log(item[i].name+'  parse已经有了')}
                else{bddc.parses.push(item[i])}
            }
            writeFile(config.dancang,JSON.stringify(bddc))
            return 'toast://添加完成'
        },item))
        d.push({
            col_type: 'text_1',
            title: '数据长度 : ' + item.length,
            desc: '所属文件：' + file
        });
        var parseobj=JSON.parse(fetch(config.dancang))
        //log(siteobj.sites)
        item.forEach((it, i) => {
            //是否有重复判断没写好  效率还低  就不加了
            //let fg=本地单仓是否已有(siteobj.sites,it)
            //log('FG : '+fg)
            let longclick = []
            if(httpfg){
                //网络文件长按菜单
            }else{
                //本地文件长按菜单
                longclick.push({
                    title: '删除',
                    js: $.toString((i, file) => {
                        if(file.startsWith('file')){
                            let j = JSON.parse(fetch(file));
                            j.parses.splice(i, 1)
                            writeFile(file, JSON.stringify(j));
                            refreshPage()
                            return 'hiker://empty'
                        }else{
                            return 'toast://非本地文件不能删除'
                        }
                        
                    }, i, file)
                })
            }
            //公共菜单
            longclick.push({
                title: '添加到本地单仓',
                js: $.toString((it) => {
                    var h=fetch(config.dancang)
                    if(h.indexOf(JSON.stringify(it))!=-1){return 'toast://这个site已经有了'}
                    else{
                        var bddc=JSON.parse(h)
                        bddc.parses.push(it)
                        writeFile(config.dancang,JSON.stringify(bddc))
                        return 'toast://添加完成'
                    }
                }, it)
            })
    
            dd(d, 't1', it.name, it, '', 'hiker://page/通用'+$.type(it), {
                it: it,
                file:file,
                longClick: longclick
            },{id:'parses'+i})
            
        })
    }else{log('strTojson 函数返回错误')}
}
function 操作sites(){
    //区分本地还是网络
    var file = MY_PARAMS.file || getParam('file', '')
    //log(file)
    var d = []  
    if(file.startsWith('http')){
        var h = 取仓库源码(file,'api')
        var httpfg=true
    }else{
        var h = fetch(file)
        var httpfg=false
    }
    //log(h)
    var rjson = strTojson(h)
    if(rjson.err=='ok'){
        var item = rjson.json.sites
        //显示的内容是 文件 file 中 sites 键下的内容
        dd(d,'tc','【 点我追加所有到本地单仓 】','','',$('#noLoading#').lazyRule((item) => {
            var h=fetch(config.dancang)
            var bddc=JSON.parse(h)
            for(let i=0;i<item.length;i++){
                if(h.indexOf(JSON.stringify(item[i]))!=-1){log(item[i].name+' 已有')}
                else{ bddc.sites.push(item[i])}
            }
            writeFile(config.dancang,JSON.stringify(bddc))
            return 'toast://添加完成'
        },item))
        d.push({
            col_type: 'text_1',
            title: '数据长度 : ' + item.length,
            desc: '所属文件：' + file
        });
        var siteobj=JSON.parse(fetch(config.dancang))
        //log(siteobj.sites)
        item.forEach((it, i) => {
            //是否有重复判断没写好  效率还低  就不加了
            //let fg=本地单仓是否已有(siteobj.sites,it)
            //log('FG : '+fg)
            let longclick = []
            if(httpfg){
                //网络文件长按菜单
            }else{
                //本地文件长按菜单
                longclick.push({
                    title: '删除',
                    js: $.toString((i, file) => {
                        if(file.startsWith('file')){
                            let j = JSON.parse(fetch(file));
                            j.sites.splice(i, 1)
                            writeFile(file, JSON.stringify(j));
                            refreshPage()
                            return 'hiker://empty'
                        }else{
                            return 'toast://非本地文件不能删除'
                        }
                        
                    }, i, file)
                })
            }
            //公共菜单
            longclick.push({
                title: '添加到本地单仓',
                js: $.toString((it) => {
                    var h=fetch(config.dancang)
                    if(h.indexOf(JSON.stringify(it))!=-1){return 'toast://这个site已经有了'}
                    else{
                        var bddc=JSON.parse(h)
                        bddc.sites.push(it)
                        writeFile(config.dancang,JSON.stringify(bddc))
                        return 'toast://添加完成'
                    }
                }, it)
            })
    
            dd(d, 't1', it.name, it, '', 'hiker://page/sitesitem', {
                it: it,
                file:file,
                longClick: longclick
            },{id:'sites'+i})
            
        })
    }else{log('strTojson 函数返回错误')}
    setResult(d)
}
function 操作sitesitem(){
    /*
    // bdh 需要本地化的键
    var bdh=[]

    if(it.api!=undefined){
        if(it.api.startsWith('http') || it.api.startsWith('./')){
            let apiurl=补全链接(it.api,file)
            dd(d,'s','访问API','','','web://'+apiurl)
            bdh.push({'api':apiurl})
        }
    }
    if(it.ext!=undefined){
        if(it.ext.startsWith('http') || it.ext.startsWith('./')){
            let exturl=补全链接(it.ext,file)
            dd(d,'s','访问EXT','','','web://'+exturl)
            bdh.push({'ext':apiurl})
        }
    }
    if(bdh.length>0){
        var 本地化按钮=$('#noLoading#').lazyRule((bdh) => {
            for(let i=0;i<bdh.length;i++){
                let k=Object.keys(bdh[i])[0]
                let h=fetch(bdh[i][k])
            }
        },bdh)
        dd(d,'s','本地化','','',本地化按钮)
    }
    */
    dd(d, 'text_center_1', '【 接口操作 】')
    var 添加到本地单仓 = $().lazyRule((it) => {
        var h=fetch(config.dancang)
        if(h.indexOf(JSON.stringify(it))!=-1){return 'toast://这个site已经有了'}
        else{
            var bddc=JSON.parse(h)
            bddc.sites.push(it)
            writeFile(config.dancang,JSON.stringify(bddc))
            return 'toast://添加完成'
        }
    }, it)
    dd(d, 't2', '添加到本地单仓','','',添加到本地单仓)
    var 本地化添至单仓 = $().lazyRule((it) => {
        var h=fetch(config.dancang)
        if(h.indexOf(JSON.stringify(it))!=-1){return 'toast://这个site已经有了'}
        else{putMyVar('todo','本地化');refreshPage()}
    }, it)
    dd(d, 't2', '本地化添至单仓','','',本地化添至单仓)
    dd(d, 'line')
    dd(d, 'text_center_1', '接口网站详情')
    var keys = Object.keys(it)
    if(getMyVar('todo')=='本地化'){
        //本地化
        for (let i = 0; i < keys.length; i++) {
            let ltype = $.type(it[keys[i]])
            if(ltype=='string'){
                if(it[keys[i]].startsWith('http')){
                    var fname=getfilename(it[keys[i]])
                    let myh=fetch(it[keys[i]],{toHex:true})
                    writeHexFile(config.otherpath+fname,myh)
                    log(fname+'   '+myh.length)
                    it[keys[i]]='./other/'+fname
                    dd(d, 't1', keys[i] + '---> ' + ltype, it[keys[i]])
                }
                if(it[keys[i]].startsWith('./')){
                    let fpath=getfilepath(file)
                    let fname=getfilename(it[keys[i]])
                    let myh=fetch(fpath+fname,{toHex:true})
                    writeHexFile(config.otherpath+fname,myh)
                    log(fname+'   '+myh.length)
                    it[keys[i]]='./other/'+fname
                    dd(d, 't1', keys[i] + '---> ' + ltype, it[keys[i]])
                }
                
            }else{
                return 'hiker://page/'+$.type(item);
            }
        }
    }else{
        for (let i = 0; i < keys.length; i++) {
            let ltype = $.type(it[keys[i]])
                dd(d, 't1', keys[i] + '---> ' + ltype, it[keys[i]], '', $('#noLoading#').lazyRule((item,file) => {
                if($.type(item)=='string'){
                    if(item.startsWith('http')){return 'web://'+item}
                    if(item.startsWith('./')){
                        let path=file.slice(0, file.lastIndexOf('/') + 1);
                        return 'web://'+path+item.slice(2,tiem.length);
                    }
                }else{
                    return 'hiker://page/'+$.type(item);
                }
                },it[keys[i]],file),{file:file,mystr:it[keys[i]]})
        }
    }


}
function 本地单仓是否已有(keyobj,item){
    var keys=Object.keys(item)
    var fg=false
    for(let i=0;i<keyobj.length;i++){
        //keyobj[i] 是对象  没有length 属性
        let k=Object.keys(keyobj[i])
        if(keys.length==k.length){fg=true}else{fg=false}
        if(fg==true && keys.includes('api')){if( item.api==keyobj[i].api){fg=false}else{fg=true}}
        if(fg==true && keys.includes('ext')){if( item.ext==keyobj[i].ext){fg=false}else{fg=true}}
        if(fg==true){return true}
    }
    return false
/* 太严格了  不适用
    for(let j=0;j<keyobj.length;j++){
        fg=false
        for(let i=0;i<keys.length;i++){
            log(item[keys[i]]!=keyobj[j][keys[i]])
            if(item[keys[i]]!=keyobj[j][keys[i]]){fg=false;break;}
            else{fg=ture}
        }
        if(fg){return ture}
    }
return false
*/
}
/**
 * 
 * @param {网址} url 完整的网络仓库网址
 * @param {使用方法} type 'api' 使用网络API获取  其他都是直接获取
 * @returns 成功返回源码  失败返回空
 */
function 取仓库源码(url,type) {
    try {
        if(type==='api'){
            var h = fetch('http://api.lige.fit/ua', {
                headers: {
                    'content-type': 'application/json'
                },
                body: {
                    'url': url
                },
                method: 'POST'
            })
        }else{
            var h=fetch(url,{headers:headerok312})
        }
        return h
    } catch (e) {
        log('取仓库源码函数错误')
        log(e.message)
    }
    return ''
}
/**
 * 全局变量
 * 1、 newbdc 新本地仓
 */
var nc = $('#noLoading#').lazyRule(() => {
    log(config)
})

/**
 * 按钮变量
 */
var 编辑本地仓说明 = $('#noLoading#').lazyRule((bdcsm) => {
    if (!fileExist(config.bdcsm)) {
        writeFile(config.bdcsm, '')
    }
    return 'editFile://' + config.bdcsm
})
var 新建本地仓 = $('#noLoading#').lazyRule(() => {
    confirm({
        title: '新建本地仓',
        content: '建了新的，老的就没啦！慎重！',
        confirm: $.toString(() => {
            var ybdc = fetch(config.dancang)
            writeFile(config.boxpath + '本地仓备份.json', JSON.stringify(ybdc))
            var bdc = {}
            var shuoming = "由海阔TVBOX插件编辑生成！"
            var spider = ""
            var wallpaper = ""
            var warningText = "接口免费整理维护，请勿付费购买"
            var sites = []
            var parses = []
            var rules = []
            var lives = []
            var flags = []
            var ads = []
            var doh = []
            var ijk = []

            bdc.shuoming = shuoming
            bdc.spider = spider
            bdc.wallpaper = wallpaper
            bdc.warningText = warningText
            bdc.sites = sites
            bdc.parses = parses
            bdc.rules = rules
            bdc.lives = lives
            bdc.flags = flags
            bdc.ads = ads
            bdc.doh = doh
            bdc.ijk = ijk
            writeFile(config.dancang, JSON.stringify(bdc))
            toast('新建完成！')
        }),
        cancel: $.toString(() => {
            refreshPage()
        })
    })
    return 'hiker://empty'
})
/**
 * 公共函数
 */
function 是否有数组属性(obj, str) {
    if (str.indexOf('.') === -1) {
        if (obj.hasOwnProperty(str) && Array.isArray(obj[str])) {
            return true
        } else {
            return false
        }
    } else {
        //str 中有点的 如： data.list
        let s = str.split('.')
        if (obj.hasOwnProperty(s[0])) {
            if (obj[s[0]].hasOwnProperty(s[1]) && Array.isArray(obj[s[0]][s[1]])) {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }

}
function 是否有字符串属性(obj, str) {
    if (str.indexOf('.') === -1) {
        if (obj.hasOwnProperty(str) && typeof (str) == 'string') {
            return true
        } else {
            return false
        }
    } else {
        //str 中有点的 如： data.list
        let s = str.split('.')
        if (obj.hasOwnProperty(s[0])) {
            if (obj[s[0]].hasOwnProperty(s[1]) && typeof (str) == 'string') {
                return true
            } else {
                return false
            }
        } else {
            return false
        }
    }

}



//利用各种方法将 str 转换成 json对象
//返回对象格式{err:'ok/no',message:'',json:{}}
function strTojson(h) {
    var json = {}
    var r = {}
    r.err = 'no'
    //标准解析
    try {
        json = JSON.parse(h)
        r.err = 'ok'
    } catch (e) {
        log('标准解析json.parse()错误 : ' + e.message)
        r.message = e.message
        r.err = 'no'
    }
    //eval 解析
    if (r.err === 'no') {
        try {
            json = eval('(' + h + ')')
            r.err = 'ok'
        } catch (e) {
            log('eval 解析错误: ' + e.message)
            r.message = e.message
            r.err = 'no'
        }
    }

    //截取sites键+eval解析  很不全面
    /*
    if(r.err==='no'){
        let h1=h.indexOf('"sites"')
        let h2=h.indexOf('}]')
        let h3='{'+h.slice(h1,h2+2)+'}'
        try {
        json=eval('(' + h3+')')
        r.err='ok'
        } catch (e) {
            log('截取sites键+eval: ' + e.message)
            r.message=e.message
            r.err='no'
        }
    }
    */
    r.json = json
    return r
}
//输入file全路径 返回最后一个“/”右面的字符串
function getfilename(file) {
    file=file.split('?')[0]
    return file.substring(file.lastIndexOf('/') + 1)
}
function getfilepath(file) {
    return file.slice(0, file.lastIndexOf('/') + 1)
}
function getparent(f) {
    log('getparent-f:' + f)
    if (f.indexOf('file://') != -1) {
        f = f.replace('file://', '')
    }
    const File = java.io.File;
    let obj = new File(f);
    return obj.getParent() + '/';
}
/**
 * 3、getfiles(f)
 * @功能1 参数 f 为目录，返回此目录下所有文件和子目录名
 * @功能2 参数 f 为文件，返回文件当前目录下所有文件和子目录名
 * @param {String} f 文件名（带路径）字符串
 * @returns json数据对象，包含基础路径，文件名数组，路径名数组
 */
function getfiles(f) {
    var data = {
        base: '/storage/emulated/0/',
        patharr: [],
        filearr: []
    }
    // f是file:///开头的 替换成空
    log('getfiles-f:' + f)
    f = f.replace('file://', '')
    var rootpath = '/storage/emulated/'
    if (rootpath.indexOf(f) != -1) {
        //f 要取得根目录之上的目录 返回空
        return data;
    }
    if (f.indexOf(rootpath) == -1) {
        //是相对路径  只能相对根目录
        if (f.startsWith('/')) {
            f = rootpath + f.slice(1)
        } else {
            f = rootpath + f
        }
        // f 是一个完整的路径 或 文件

    }

    const File = java.io.File;
    let obj = new File(f);

    if (obj.isDirectory()) {
        data.base = obj.getPath() + '/'
        var path = obj
    } else {
        data.base = obj.getParent() + '/'
        var path = obj.getParentFile()
    }
    let list = path.listFiles();
    let d1 = []
    let d2 = []
    for (let i in list) {

        if (list[i].isDirectory()) {
            //如果是目录
            d1.push(list[i].getName())
        } else {
            //如果是文件
            d2.push(list[i].getName())
        }
    }
    //数组排序
    d1.sort((a, b) => {
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });

    d2.sort((a, b) => {
        if (a < b) {
            return -1;
        } else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    });
    data.patharr = d1
    data.filearr = d2
    return data
}


//取当前事件的字符串格式 返回如：[20231204]
function getnowtime() {
    let date = new Date(),
        year = date.getFullYear(), //获取完整的年份(4位)
        month = date.getMonth() + 1, //获取当前月份(0-11,0代表1月)
        strDate = date.getDate() // 获取当前日(1-31)
    if (month < 10) month = `0${month}` // 如果月份是个位数，在前面补0
    if (strDate < 10) strDate = `0${strDate}` // 如果日是个位数，在前面补0

    return `[${year}${month}${strDate}]`
}
/**
 *  文件访问(url,headers,body,method,timeout,withStatusCode,withHeaders,onlyHeaders,toHex)
 * @param {网址} url 网络地址
 * @param {对象} headers 请求头 默认MOBILE_UA
 * @param {对象} body POST时使用 {a:'aa',b:'bb'} 请求时自动转换成a=aa&b=bb
 * @param {字符串} method GET POST
 * @param {数值} timeout 默认5000 毫秒
 * @param {逻辑} withStatusCode 带返回状态，这时返回的是一个json对象字符串，需要json.prars转换
 * @param {逻辑} withHeaders 带返回头，返回对象同上
 * @param {逻辑} onlyHeaders 只返回头，返回对象同上
 * @param {逻辑} toHex 返回二进制源码
 * @returns 返回字符串，当参数中有带返回头要求时，返回的是json对象字符串，其body属性内容为网页源码
 */
function 文件访问(url, headers, body, method, timeout, withStatusCode, withHeaders, onlyHeaders, toHex) {
    var hd = { "User-Agent": MOBILE_UA }
    var bd = {}
    var ext = {}
    //log('文件访问的参数：headers')
    if (headers == '' || headers == undefined) { ext.headers = hd } else { ext.headers = headers }
    //log(ext.headers)
    if (body == '' || body == undefined) { ext.body = bd } else { ext.body = body }
    if (method == '' || method == undefined) { ext.method = 'GET' } else { ext.method = method }
    if (timeout == '' || timeout == undefined) { ext.timeout = 5000 } else { ext.timeout = timeout }
    if (withStatusCode === true) { ext.withStatusCode = withStatusCode }
    if (withHeaders === true) { ext.withHeaders = withHeaders }
    if (onlyHeaders === true) { ext.onlyHeaders = onlyHeaders }
    if (toHex === true) { ext.toHex = toHex }
    //log('文件访问的参数：')
    //log(ext)
    //处理分页链接地址 用当前页号替换
    //http://www.98dyw.com/dianyingpian/index1.html[firstPage=http://www.98dyw.com/dianyingpian/index.html]
    if (url.indexOf('firstPage') != -1) {
        //有双链接
        if (MY_PAGE === 1) {
            url = url.split('[firstPage=')[1].slice(0, -1)
        } else {
            url = url.split('[firstPage=')[0]
        }
    }
    try {
        var str = fetch(url, ext)
    } catch (e) {
        log('error：' + url + '!!!' + e.message);
    }

    return str
}

/**
 * 接口文件函数 取大类  返回大类对象数组
 * 大类=[{type_id:'大类id',type_pid:'父级id',type_name:'大类名',type_url:'大类链接'}]
 * 
 */

/**
 * 取大类(html,type)
 * @param {String} html 接口文件代码
 * @param {String} type 接口文件类型 
 * @returns 大类对象数组 大类=[{type_id:'大类id',type_pid:'父级id',type_name:'大类名',type_url:'大类链接'}]
 */
function 取大类() {
    //var 大类=[]
    var html = 全局接口文件内容
    var type = 全局接口文件类型
    //读文件 不放在函数内
    /*
    var str=文件访问(filename,'','','','',true)
    var strjson=JSON.parse(str)
    if(strjson.statusCode!=200){
        log('文件访问返回码错误：'+strjson.statusCode)
        return 大类
    }
    var html=strjson.body
    */
    switch (type) {
        case 'xyqh':
            // XYQH ================= 取大类代码开始
            //大类对象中 type_id 是 顺序序号
            try {
                var f = {}
                eval('f=' + html);
            } catch (er) {
                log('取大类 json转换时发生错误：' + er.message)
                break;
            }
            //log(f)
            //let curl = f.class_url || f.分类链接
            let cname = f.class_name || f.分类名称
            let cvalue = f.class_value || f.分类名称替换词
            let hd = f.headers || f.请求头参数
            let bm = f.coding_format || f.网页编码格式
            // 编码格式没处理  碰到再说
            var rule = {}
            switch (hd) {
                case 'PC_UA':
                    rule.headers = { "User-Agent": PC_UA }
                    break;
                case 'Windows':
                    rule.headers = { "User-Agent": PC_UA }
                    break;
                case 'MOBILE_UA':
                    rule.headers = { "User-Agent": MOBILE_UA }
                    break;
                case '手机':
                    rule.headers = { "User-Agent": MOBILE_UA }
                    break;
                default:
                    if (hd.indexOf('#') != -1) {
                        hds = hd.split('#')
                        let hdobj = {}
                        let pb = ["手机", "MOBILE_UA", "PC_UA", "Windows"]
                        for (let i = 0; i < hds.length; i++) {

                            //log(hds[i])
                            let item = hds[i].split('$')
                            if (pb.includes(item[1])) { hdobj[item[0]] = eval(item[1]) }
                            else { hdobj[item[0]] = item[1] }
                            //rule.headers['"'+item[0]+'"']=eval(item[1])
                            //rule.headers['Referer']=WebView
                            //log(rule.headers)
                            //log('不知道为啥 referer 填不进去')
                        }
                        rule.headers = hdobj
                        //hdstr=hdstr.slice(0,hdstr.length-1)+'}'
                        //let a='{"\"Referer\"":"WebView","\"User-Agent\"":"MOBILE_UA"}'
                        //let b=(JSON.parse(a))
                        //log(hdstr)
                        //rule.headers=JSON.parse(hdstr)

                    }

            }
            //请求头有多个参数时还是错误
            log(rule.headers)
            //User-Agent$PC_UA#Referer$http://ww.baidu.com#Cookie$ser=ok
            //if(hd.indexOf('#')!=-1)
            //rule.headers='{"User-Agent": '+hd+'}'
            var names = cname.split('&')
            if (cvalue.indexOf('＆＆') != -1) {
                var values = cvalue.split('＆＆')
            } else {
                var values = cvalue.split('&')
            }
            if (names.length != values.length) {
                log('XYQH取大类错误，大类名称和替换词个数不同，请检查接口文件！')
                break;
            }
            for (let i = 0; i < names.length; i++) {
                let linshi = {}
                linshi.type_name = names[i]
                linshi.type_url = values[i]
                linshi.type_id = i + ''
                linshi.type_pid = '0'
                大类.push(linshi)
            }
            // XYQH ================= 取大类代码开始
            break;
        case 'js':
            // JS ================= 取大类代码开始
            var rule = 合并模板js()

            //有 则用正则取原网页大类  没有的 用class_name class_url
            if (rule.class_parse != undefined) {
                //用正则取
                log('大类标题的提取规则：' + rule.class_parse)
                let mygz = rule.class_parse.split(';')
                let myhost = rule.host
                //let myurl = rule.url
                // 注意： 直接读域名地址可能会有些问题  【碰到再改】
                //log(rule.headers)
                if (rule.headers != undefined) {
                    var h = 文件访问(myhost, rule.headers)
                    //log('取大类 获取源码长度：'+h.length)
                } else {
                    var h = 文件访问(myhost)
                }
                log('取大类 js 文件访问返回长度:' + h.length)
                //长度小于1000 就是返回个寂寞
                if (h.length < 1000) { return 大类 }
                //let h = fetch(myhost)
                //列表
                //如果取列表的规则没有&&  就加上   要不海阔取不出来
                if (mygz[0].indexOf('&&') == -1) { mygz[0] = 'body&&' + mygz[0] }
                let list = pdfa(h, mygz[0])
                if (list.length > 0) {
                    //处理规则最后一项正则中 / 的问题，海阔里必须加转义
                    let rr = mygz[3].replace(/(\/)/g, '\\/')
                    if (rr.indexOf('&&') == -1) { rr = rr.replace(' ', '&&') }
                    //log(rr)
                    let treg = eval('/' + rr + '/gi')
                    for (let i = 0; i < list.length; i++) {
                        //大类名
                        let tname = pdfh(list[i], mygz[1])
                        //大类链接
                        let turl = pdfh(list[i], mygz[2])
                        //log(tname + ' | ' + turl)
                        //使用正则提取有用的链接
                        let tstr = turl.match(treg)
                        if (tstr) {
                            大类.push({
                                type_id: RegExp.$1,
                                type_pid: '0',
                                type_name: tname,
                                type_url: turl
                            })
                        }
                    }
                }
            } else {
                //用class_name class_url
                let tname = rule.class_name.split('&')
                let turl = rule.class_url.split('&')
                if (tname.length != turl.length) {
                    log('取大类 js 模板中大类名和大类链接数不同，请核对接口文件！')
                    break;
                }
                for (let i = 0; i < tname.length; i++) {
                    大类.push({
                        type_id: i + '',
                        type_pid: '0',
                        type_name: tname[i],
                        type_url: turl[i]
                    })
                }
            }
            // JS ================= 取大类代码开始
            break;
        case 'xbiu':
            // XBIU ================= 取大类代码开始
            // XBIU ================= 取大类代码开始
            break;
        case '采集json':
            // 采集json ================= 取大类代码开始
            // 采集json ================= 取大类代码开始
            break;
        case '采集xml':
            // 采集xml ================= 取大类代码开始
            // 采集xml ================= 取大类代码开始
            break;

        default:
        // code block for default case
    }
    //log('取大类得到的全局rule:')
    //log(rule)
    //log(大类)
    return rule
}
/**
 * 1、取栏目数据XYQH(f, gz)
 * @功能 根据网页代码或json对象内容提取栏目名数组和对应的链接数组
 * @json对象获取 var json = {};eval('json=' + fetch(file));
 * @涉及函数 补全链接()
 * @param {JSON} f 接口文件的json对象
 * @param {String} gz 取栏目的规则,用';'分开，可省了。填写，取'json.首页推荐链接'地址的栏目内容。不填写，根据json生成。
 * @规则说明 格式 列表提取规则;标题提取规则;链接提取规则。链接提取
 * @returns json对象
 */

function 处理大类链接() {
    var html = 全局接口文件内容
    var type = 全局接口文件类型
    switch (type) {
        case 'xyqh':
            // XYQH ================= 处理大类链接代码开始
            try {
                var f = {}
                eval('f=' + html);
            } catch (er) {
                log('处理大类链接 json转换时发生错误：' + er.message)
                break;
            }
            //log(f)
            let curl = f.class_url || f.分类链接
            for (let i = 0; i < 大类.length; i++) {
                大类[i].type_url = curl.replace(/{cateId}/g, 大类[i].type_url)
                大类[i].type_url = 大类[i].type_url.replace(/{catePg}/g, 'fypage')
                大类[i].type_url = 大类[i].type_url.replace(/{\w+}/g, '')
            }
            // XYQH ================= 处理大类链接代码开始
            break;
        case 'js':
            // JS ================= 处理大类链接代码开始
            for (let i = 0; i < 大类.length; i++) {
                //log(大类[i].type_url)
                //log(rule.url)
                //如果url中有fyclass 就替换  然后把fyfilter去掉
                let u = rule.url
                if (u.indexOf('fyclass') != -1) {
                    u = u.replace('fyclass', 大类[i].type_url)
                    u = u.replace('fyfilter', '')
                    大类[i].type_url = rule.host + u
                    //log(大类[i].url)
                }
                //* 更换后部分网站会出错
                else {
                    u = u.replace('fyfilter', rule.filter_url)
                    u = u.replace('{{fl.cateId}}', 大类[i].type_id)
                    大类[i].type_url = rule.host + u.replace(/{{\w+.\w+}}/g, '')
                    log(大类[i].type_url)
                }

            }
            // JS ================= 处理大类链接代码开始
            break;
        case 'xbiu':
            // XBIU ================= 处理大类链接代码开始
            // XBIU ================= 处理大类链接代码开始
            break;
        case '采集json':
            // 采集json ================= 处理大类链接代码开始
            // 采集json ================= 处理大类链接代码开始
            break;
        case '采集xml':
            // 采集xml ================= 处理大类链接代码开始
            // 采集xml ================= 处理大类链接代码开始
            break;

        default:
        // code block for default case

    }
    //log(大类)
}
function 合并模板js() {
    //使用到的外部全局变量:
    //全局接口文件内容
    try {
        //eval(JSON.parse(fetch(muban)))
        var muban = getjsMubans();
        //道长js的接口文件是代码  可以直接eval
        eval(全局接口文件内容)
        //成功后 可以使用rule对象
    } catch (er) {
        log('取大类 js eval转换时发生错误：' + er.message)
        return undefined
    }
    if (rule.模板 == undefined) {
        var kk = Object.keys(muban.默认)
        for (k in kk) {
            rule[kk[k]] = rule[kk[k]] || muban.默认[kk[k]]
        }
    } else {
        var kk = Object.keys(muban[rule.模板])
        for (k in kk) {
            rule[kk[k]] = rule[kk[k]] || muban[rule.模板][kk[k]]
        }
    }
    return rule
}

function 取影片数据() {
    var html = 全局接口文件内容
    var type = 全局接口文件类型
    var h = 全局网页源码
    var d = []
    switch (type) {
        case 'xyqh':
            // XYQH ================= 处理大类链接代码开始
            var f = {}
            eval('f=' + html);
            let fpage = f.firstpage || f.分类起始页码
            //分类链接 情况一：
            //http://xxx.com/abc/{cateId}-{catePg}.html[firstPage=http://xxx.com/abc/{cateId}]
            //let curl = f.class_url || f.分类链接
            let cname = f.class_name || f.分类名称
            //let cvalue = f.class_value || f.分类名称替换词
            let mode = f.cat_mode || f.分类截取模式
            let isjson = f.catjson_twice || f.分类Json数据二次截取
            let arr = f.cat_arr_rule || f.分类列表数组规则
            let isjsoup = f.cat_is_jsoup || f.分类片单是否Jsoup写法
            let tit = f.cat_title || f.分类片单标题
            let curl = f.cat_url || f.分类片单链接
            let pic = f.cat_pic || f.分类片单图片
            let stit = f.cat_subtitle || f.分类片单副标题
            let qian = f.cat_prefix || f.分类片单链接加前缀
            let hou = f.cat_suffix || f.分类片单链接加后缀
            var list = pdfa(h, arr)
            log('取影片数据 xyqh 列表截取规则：' + arr)
            log('截取到数组长度:' + list.length)
            list.forEach(it => {
                d.push({
                    tit: pdfh(it, tit),
                    url: qian + pdfh(it, curl) + hou,
                    img: pdfh(it, pic),
                    stit: pdfh(it, stit)
                })
            })
            // XYQH ================= 处理大类链接代码开始
            break;
        case 'js':
            // JS ================= 处理大类链接代码开始
            //取大类之后 rule已经是全局变量了

            log('JS 接口文件 一级 ：' + rule.一级)
            let gz = rule.一级.split(';')
            if (gz[0].indexOf('&&') == -1) { gz[0] = gz[0].replace(' ', '&&') }
            let list = pdfa(h, gz[0])
            log('list 获取正则：' + gz[0] + ' 最后获取数量：' + list.length)
            for (let i = 0; i < list.length; i++) {
                d.push({
                    title: pdfh(list[i], gz[1]),
                    img: pdfh(list[i], gz[2]),
                    desc: pdfh(list[i], gz[3]),
                    url: rule.host + pdfh(list[i], gz[4])
                })
            }
            // JS ================= 处理大类链接代码开始
            break;
        case 'xbiu':
            // XBIU ================= 处理大类链接代码开始
            // XBIU ================= 处理大类链接代码开始
            break;
        case '采集json':
            // 采集json ================= 处理大类链接代码开始
            // 采集json ================= 处理大类链接代码开始
            break;
        case '采集xml':
            // 采集xml ================= 处理大类链接代码开始
            // 采集xml ================= 处理大类链接代码开始
            break;

        default:
        // code block for default case
    }
    return d
}

function 函数模板(html, type, 大类) {
    switch (type) {
        case 'xyqh':
            // XYQH ================= 处理大类链接代码开始

            // XYQH ================= 处理大类链接代码开始
            break;
        case 'js':
            // JS ================= 处理大类链接代码开始
            try {
                //eval(JSON.parse(fetch(muban)))
                var muban = getjsMubans();
                //道长js的接口文件是代码  可以直接eval
                eval(html)
                //成功后 可以使用rule对象
            } catch (er) {
                log('取大类 js eval转换时发生错误：' + er.message)
                return 大类
            }
            //取子模板内的属性名
            //log(rule)
            //将接口文件内容和模板内容合并
            if (rule.模板 == undefined) {
                var kk = Object.keys(muban.默认)
                for (k in kk) {
                    rule[kk[k]] = rule[kk[k]] || muban.默认[kk[k]]
                }
            } else {
                var kk = Object.keys(muban[rule.模板])
                for (k in kk) {
                    rule[kk[k]] = rule[kk[k]] || muban[rule.模板][kk[k]]
                }
            }
            // JS ================= 处理大类链接代码开始
            break;
        case 'xbiu':
            // XBIU ================= 处理大类链接代码开始
            // XBIU ================= 处理大类链接代码开始
            break;
        case '采集json':
            // 采集json ================= 处理大类链接代码开始
            // 采集json ================= 处理大类链接代码开始
            break;
        case '采集xml':
            // 采集xml ================= 处理大类链接代码开始
            // 采集xml ================= 处理大类链接代码开始
            break;

        default:
        // code block for default case
    }

}

function 取栏目数据XYQH(f, gz) {
    var data = {
        err: '',
        //栏目名数组 
        name: [],
        //栏目名对应的地址链接（补全后地址）
        url: []
    }
    var reg = '/{cateId}/g'
    var url = f.rcmed_url || f.首页推荐链接
    if (gz != undefined && gz != '') {
        //有规则
        var html = mfetch(url)
        // gz 格式 列表;标题;链接
        let cname = f.class_name || f.分类名称
        if (html.indexOf(cname.split('&')[0]) = -1) { data.err = '网页内容错误' }
        var gzs = gz.split(';')
        var list = pdfa(html, gzs[0])
        for (let i = 0; i < list.length; i++) {
            data.name.push(pdfh(list[i], gzs[1]))
            let u = pdfh(list[i], gzs[2])
            u = 补全链接(u, url)
            data.url.push(u)
        }

    } else {
        //无规则，使用json数据
        let curl = f.class_url || f.分类链接
        let cname = f.class_name || f.分类名称
        let cvalue = f.class_value || f.分类名称替换词
        //let qian = f.cat_prefix || f.分类片单链接加前缀
        //let hou = f.cat_suffix || f.分类片单链接加后缀
        data.name = cname.split('&')
        if (cvalue.indexOf('＆＆') != -1) {
            var v = cvalue.split('＆＆')
        } else {
            var v = cvalue.split('&')
        }

        for (let i = 0; i < v.length; i++) {
            let u = curl.replace(eval(reg), v[i])
            u = clearurl(u)
            data.url.push(u)
            if (i == 0) {
                putMyVar('当前连接', u);
                log('取栏目数据 设置当前连接：' + u)
            }
        }
    }

    return data
}

/**
 * 2、补全链接(a, b)
 * @功能 如果参数a为不完全链接地址，函数将根据参数b将其补全
 * @param {String} a 要补全的链接地址
 * @param {String} b 用来提取补全地址的链接
 * @returns 补全后的链接地址
 */
function 补全链接(a, b) {
    if (a.startsWith('http')) {
        return a
    }
    if (a.startsWith('//')) {
        return 'http:' + a
    }
    if (a.startsWith('/')) {
        if (b.startsWith('http')) {
            let s = b.split('://')
            let host = s[0] + '://' + s[1].slice(0, s[1].indexOf('/'))
            return host + a
        } else {
            return 'err:基础链接b，必须以http开头'
        }
    }
    if (a.startsWith('./')) {
        if (b.startsWith('http')) {
            let host = b.slice(0, b.lastIndexOf('/'))
            return host + a.slice(1, a.length)
        } else {
            return 'err:基础链接b，必须以http开头'
        }
    }
    return 'err:未知错误，请查看补全链接函数'
}
/**
 * 
 * @param {string} str 路径字符串 要用完全路径 可以用file:///开头 或者 /storage/emulated/0/
 * @returns 
 */
function makedir(str) {
    const File = java.io.File;

    let obj = new File(str.replace('file://', ''));
    return obj.mkdir()
}


/**
 * 4、检查变量()
 * @功能 测试函数，检查所有传入到参数时候有undefined，没有返回 true 否则返回 false
 * @returns 
 */
function 检查变量() {
    //	var info = "今日签到的学生有：";
    for (let i = 0; i < arguments.length; i++) {

        if (arguments[i] == undefined) {
            return false
        }
    }
    return true

}

/**
 * 5、dd(data,a, b, c, d, e, f)
 * @功能 向海阔组件数组添加组件
 * @param {海阔组件数组} data 组件数组
 * @param {组件样式str} a 组件样式
 * @param {组件标题str} b 组件标题
 * @param {组件简介str} c 组件简介
 * @param {组件图片链接str} d 组件图片链接
 * @param {组件跳转链接str} e 组件跳转链接
 * @param {扩展JSON对象} f 组件extra扩展对象，是一个json数据对象 
 */
function dd(data, a, b, c, d, e, f) {
    var col = ''
    switch (a) {
        case 't1':
            col = 'text_1';
            break;
        case 't2':
            col = 'text_2';
            break;
        case 'tc':
            col = 'text_center_1';
            break;
        case 'm1':
            col = 'movie_1_left_pic';
            break;
        case 'm2':
            col = 'movie_2';
            break;
        case 'm3':
            col = 'movie_3_marquee';
            break;
        case 's':
            col = 'scroll_button';
            break;
        case 'f':
            col = 'flex_button';
            break;
        case 'l':
            col = 'line';
            break;
        case 'lb':
            col = 'line_blank';
            break;
        default:
            col = a;
            break;
    }

    data.push({
        col_type: col,
        title: b,
        desc: c,
        img: d,
        url: e,
        extra: f
    })
}


/**
 * 6、function mfetch(url, thgz)  取网页源码
 * @功能 获取网页源码，代替fetch，同时处理页面规则替换。功能还不完善，需要后续修改
 * @说明1 支持 url2[firstPage=url1] 链接
 * @说明2 访问前利用规则替换访问链接
 * @param {String} url 页面访问链接
 * @param {String} thgz 链接替换规则，需要成对出现，每一对中用后一个替换前一个
 * 例如：1;2;3;4 中1、2为一对，3、4为一对。先用2替换1，再用4替换3。
 * @规则说明 “+” 直接在练就后添加替换字符串，“-” 将链接中包含替换字符串的部分替换成空。fypage和{catePg} 替换成 MY_PAGE
 * @returns {String} 返回链接源码
 */
function mfetch(url, thgz) {
    var url1 = ''
    var url2 = ''
    var html = ''
    // 是第一页且有分页
    if (MY_PAGE === 1 && url.indexOf('firstPage=') != -1) {
        url = url.split('[firstPage=')[1].replace(']', '')
    } else {
        url = url.split('[firstPage=')[0]
    }
    //开始替换链接
    if (thgz != undefined) {
        var gzs = thgz.split(';')
        for (let i = 0; i < gzs.length; i = i + 2) {
            switch (gzs[i]) {
                case '+':
                    url = url + gzs[i + 1];
                    break;
                case '-':
                    url = url.replace(gzs[i + 1], '');
                    break;
                case 'fypage':
                    url = url.replace('fypage', MY_PAGE);
                    break;
                case '{catePg}':
                    url = url.replace('{catePg}', MY_PAGE);
                    break;
                default:
                    url = url.replace(gzs[i], gzs[i + 1]);
            }
        }
    }
    html = fetch(url)
    //过数字验证
    if (/验证码|系统安全验证/.test(html)) {
        let headers = {
            "User-Agent": MOBILE_UA,
            "Referer": url
        };
        MY_HOME = getHome(url);
        let ssyz = 'TloGnnikThrfs/5fDNlk5CSsbaGtAH7W/uMZjuYoIupB6bCoo9CotLQHfPIdGgbkbynKqL2aUE2Xy558X2QxHYtTU09vD+4oaCDIuSZO7nxDbLfRGfWj7zql+yMbvF+aJoD/m6Psfw/PyYOAp/ZVGdrPzaCByfd0HL5DFVSw+YF2OC40V8SP9RxdFKKdrBuPxCWdxUCFrJ+1lRy/TU3LC84C4xxEBhgud7RtBp0zZArqBE06+Z3JtDP0eFCz/D5X0409qPHK3e1y/LuUgccuxpHnjYLE1GjlP8wYA2hQWe7yPngggQBHw33/gvb3tuCcxEKTWgmah/R32AH9ZF8jF7WemT26lUizVXe/spCdhDgHR/zUhODD4PO6glI8JPhdu+VwfPyRLG2D7CUo1L6SIF+0fYf0oTOWN13UPITo5+uZd/WnQQLU8NYx/WFCThEnkbzln9YGt60fRxsH+8uMDFgaBiC+z2SpcxB9gZ6GXypLSXWaj+qEUbGJKEx+jK/v5fnrkIhCdwNbkp9dRks6dmlYlBifzoWF8RkuC3rqPtoScBkMOMZu7GiVtoHEdHUozmnUIdrU1LGIqq9WnG7X2a3yH8s65mjLuLnd3q0U8v+LMPnHL2/GjQuTQKVh+RKEPqK/JdrChGLNrjcHvLHDbHEshrGZuQOdEphbx/PkhkvaYy4K1MO84R17guRsKs/V6niUPaL+XbQ7c3fqJS4VHJwludJTDe02euffGCm0PJIPlAOgLHnX0izJhA6q738R2UwQcWBQjJt79aF+kyqSdyt1QPVQVjaC3IpRf7PgsDhEJ7bi9nSclyIzgJ9DCJ4T+8dG1xHhKyZasT7L/x9Lfr1Mgs8nBZER2W9ax7iTkNK+X5ACU//p/YoP/uAanDtb3D0iKUUuXFH+Jbb0x1P322S2w6BJ46nuNHBMHTpVuWwhZeZzriGh7qoOywLWiExBMKyxTGLnmKh7r03/yXKYWIJnpBN2MMycVHRZJ7RumHV4CIsVrq7iRP48823RJVt9OtyP7uuc3wBBV3kcZUzbbaYdWBx1+Au+Od2u7lR6joOL810mcJm/f7J5TvGQP6HGph1YHHX4C7453a7uVHqOgyjjh5EBd720MEBY23c+TKq/z9UpWDDOg48ZFnwSIhFqitWdiZiqsaYuN0/SXwiK8EG9eQ29u2XDJoDW4mlwtcRO7vaX5XcFsgf4/mLU07mi';
        evalPrivateJS(ssyz);

        let vcode = getVCode2(MY_HOME + '/index.php/verify/index.html?', JSON.stringify(headers), 'num');
        fetch(MY_HOME + html.match(/\/index.php.*?verify=/)[0] + JSON.parse(vcode).ret, {
            headers: headers,
            method: 'POST'
        });
    }
    html = fetch(url, {
        "User-Agent": MOBILE_UA,
        "Referer": url
    })
    //log(html)
    return html
}

//读取链接内容  不用判断两次
//问题:链接中的替换词没有替换干净，访问会出现错误
/*
try {
    //html = fetch(url)
    // 如果需要丰富功能  在这里改
    log('mfetch访问的地址：' + url)
    html = JSON.parse(fetch(url, {
        withHeaders: true,
        withStatusCode: true
    }))
    if (html.statusCode != 200) {
        html = JSON.parse(fetch(url, {
            withHeaders: true,
            withStatusCode: true
        }))
        if (html.statusCode != 200) {
            return '网页读取错误'
        }
    }
} catch (err) {
    log("错误描述：" + err.message);
}
return html.body
*/


/**
 * 7、取分类数据XYQH(f, url) 取页面中要显示的数据，可以直接当海阔组件组用，但是不灵活，没处理错误
 * @param {JSON} f 接口文件的json对象，用来提供各项提取规则
 * @param {String} url 要提取数据的分类链接
 * @url说明 这个链接是“取栏目数据XYQH(f, gz)”函数返回json对象中的url数组中的数据
 * @returns 
 */
function 取分类数据XYQH(f, url) {

    let msg = {
        err: "",
        arr: [],
        直接播放: {}
    }

    let fpage = f.firstpage || f.分类起始页码
    //分类链接 情况一：
    //http://xxx.com/abc/{cateId}-{catePg}.html[firstPage=http://xxx.com/abc/{cateId}]
    //let curl = f.class_url || f.分类链接
    let cname = f.class_name || f.分类名称
    //let cvalue = f.class_value || f.分类名称替换词
    let mode = f.cat_mode || f.分类截取模式
    let isjson = f.catjson_twice || f.分类Json数据二次截取
    let arr = f.cat_arr_rule || f.分类列表数组规则
    let isjsoup = f.cat_is_jsoup || f.分类片单是否Jsoup写法
    let tit = f.cat_title || f.分类片单标题
    let curl = f.cat_url || f.分类片单链接
    let pic = f.cat_pic || f.分类片单图片
    let stit = f.cat_subtitle || f.分类片单副标题
    let qian = f.cat_prefix || f.分类片单链接加前缀
    let hou = f.cat_suffix || f.分类片单链接加后缀

    //片单链接是否直接播放，0否，1分类片单链接直接播放，2详情选集链接直接播放。
    //设置成直接播放后，后面3个参数请注意该留空的请务必留空。
    msg.直接播放.shi = f.force_play || f.链接是否直接播放
    //直接播放链接补前缀
    msg.直接播放.qian = f.play_prefix || f.直接播放链接加前缀
    //直接播放链接补后缀，设置为#isVideo=true#可强制识别为视频链接
    msg.直接播放.hou = f.play_suffix || f.直接播放链接加后缀
    //直接播放链接设置请求头，只对直链视频有效，每一组用#分开
    msg.直接播放.header = f.play_header || f.直接播放直链视频请求头


    //log('访问分类网址：' + url)
    //使用mfetch函数处理页码替换问题
    var h = mfetch(url, '{catePg}')
    if (h.indexOf(cname.split('&')[0]) == -1) {
        msg.err = '网页代码中没有分类标题（' + cname.split('&')[0] + '），可能发生网页错误！/n '
        log(msg.err)
        //log(h)
        return msg
    }
    log('获取源码长度：' + h.length)
    log('分类列表数组规则：' + arr)
    var list = pdfa(h, arr)
    log('截取到数组长度:' + list.length)
    list.forEach(it => {
        msg.arr.push({
            tit: pdfh(it, tit),
            url: qian + pdfh(it, curl) + hou,
            pic: pdfh(it, pic),
            stit: pdfh(it, stit)
        })
    })
    msg.err = ''
    return msg
}

/**
 * 8、显示大类(data, tourl) 在海阔子页上显示大类按钮
 * @功能 将“取栏目数据XYQH(f, gz)”返回的json对象显示到海阔子页面上
 * @param {JSON} data  取栏目数据XYQH(f, gz) 返回的对象
 * @param {String} tourl 海阔子页链接。可省略。有 点击按钮跳转到子页,url传实际链接。无 本页刷新。
 * @按钮保存变量1 putMyVar('当前连接',实际链接) 将点击按钮产生的实际链接存储到“当前连接”中
 * @按钮保存变量2 putMyVar('点击序号',i) 点击发生时，大类按钮的序号，从0开始
 * @returns 
 */
function 显示大类(data, tourl) {
    var d = []
    if (tourl != undefined) {
        //点击后跳转到tourl指向的子页
        for (let i = 0; i < data.name.length; i++) {
            d.push({
                col_type: 'scroll_button',
                title: data.name[i],
                url: tourl,
                extra: {
                    url: data.url[i]
                }
            })
        }
    } else {
        //本页刷新
        for (let i = 0; i < data.name.length; i++) {
            var b = $('#noLoading#').lazyRule((it, i) => {
                putMyVar('当前连接', it)
                putMyVar('点击序号', i + '')
                //动态添加不用刷新页面
                //MY_RULE.url=it
                refreshPage()
                //必须返回一个链接，不然报错
                return 'hiker://empty'
            }, data.url[i], i)

            d.push({
                col_type: 'scroll_button',
                title: data.name[i],
                url: b
            })
        }

    }
    return d
}
/**
 * 9、添加结果到组件组(data,obj,col,tourl,json) 添加 取分类数据XYQH 函数结果数组到海阔组件组，方便显示
 * @param {组件对象组} data 目标组件组
 * @param {JSON对象} obj 取分类数据XYQH(f, url)返回的json对象
 * @param {String} col 海阔组件的显示样式
 * @param {String} tourl 海阔子页链接
 * @param {String} str 传给下一页的字符串，可以夹带一些东西。比如：json接口文件名
 * @传入下一页 url：url链接 u：url链接 tit：标题 pic：图片链接 str：下一页用到的字符串
 */
function 添加结果到组件组(data, obj, col, tourl, str) {

    if (obj.直接播放.shi === '0' || obj.直接播放.shi === '否') {
        // 0 不直接播放
        for (i = 0; i < obj.arr.length; i++) {
            json.url = obj.arr[i].url;
            data.push({
                col_type: col,
                title: obj.arr[i].tit,
                desc: obj.arr[i].stit,
                img: obj.arr[i].pic,
                url: tourl,
                extra: {
                    url: obj.arr[i].url,
                    u: obj.arr[i].url,
                    tit: obj.arr[i].tit,
                    pic: obj.arr[i].pic,
                    str: str
                }
            })
        }
    } else {
        //直接播放，在海阔里直接使用video://嗅探
        for (i = 0; i < obj.arr.length; i++) {
            data.push({
                col_type: col,
                title: obj.arr[i].tit,
                desc: obj.arr[i].stit,
                img: obj.arr[i].pic,
                url: 'video://' + obj.arr[i]
            })
        }
    }


}
/**
 * 10、添加详情数据到组件组(d,html,f)  添加影片播放数据到海阔组件的显示数组中
 * @param {海阔组件对象数组} d 
 * @param {String} html 网页源码
 * @param {接口文件json对象} f 接口文件对象 
 */
function 添加详情数据到组件组(d, html, f) {
    dd(d, 'pic_1_center', '', '', MY_PARAMS.pic)
    dd(d, 'text_center_1', MY_PARAMS.tit)
    //项目信息jsoup与正则截取写法切换，1 是 为jsoup写法(默认)，0 否 为正则截取写法
    proj_is_jsoup = f.proj_is_jsoup || f.详情是否Jsoup写法
    proj_cate = f.proj_cate || f.类型详情
    proj_year = f.proj_year || f.年代详情
    proj_area = f.proj_area || f.地区详情
    proj_actor = f.proj_actor || f.演员详情
    proj_plot = f.proj_plot || f.简介详情

    tab_arr_rule = f.tab_arr_rule || f.线路列表数组规则
    tab_title = f.tab_title || f.线路标题

    list_arr_rule = f.list_arr_rule || f.播放列表数组规则
    epi_arr_rule = f.epi_arr_rule || f.选集列表数组规则
    epi_is_jsoup = f.epi_is_jsoup || f.选集标题链接是否Jsoup写法
    epi_title = f.epi_title || f.选集标题
    epi_url = f.epi_url || f.选集链接
    epi_reverse = f.epi_reverse || f.是否反转选集序列
    epiurl_prefix = f.epiurl_prefix || f.选集链接加前缀
    epiurl_suffix = f.epiurl_suffix || f.选集链接加后缀
    //详细介绍
    log('详情是否Jsoup写法:' + proj_is_jsoup)
    if (proj_is_jsoup === '1' || proj_is_jsoup === '是') {
        //jsoup写法  用pdfh 函数
        var lx = pdfh(html, proj_cate)
        var nd = pdfh(html, proj_year)
        var dq = pdfh(html, proj_area)
        var yy = pdfh(html, proj_actor)
        var jj = pdfh(html, proj_plot)
    } else {
        //正则写法
        //要用toReg函数处理一下表达式中特殊符号,否则会错误
        if (proj_cate != '' && proj_cate != undefined) {
            var leixing = "/" + toReg(proj_cate) + "/"
            log('正则类型：' + leixing)
            leixing.replace('&&', '.*?')
            var lx = html.match(eval(leixing))
        } else { var lx = '' }

        if (proj_year != '' && proj_year != undefined) {
            var niandai = "/" + toReg(proj_year) + "/"
            log('正则年代：' + niandai)
            niandai.replace('&&', '.*?')
            var nd = html.match(eval(niandai))
        } else { var nd = '' }
        if (proj_area != '' && proj_area != undefined) {
            var diqu = "/" + toReg(proj_area) + "/"
            log('正则地区：' + diqu)
            diqu.replace('&&', '.*?')
            var dq = html.match(eval(diqu))
        } else { var dq = '' }
        if (proj_actor != '' && proj_actor != undefined) {
            var yanyuan = "/" + toReg(proj_actor) + "/"
            log('正则演员：' + yanyuan)
            yanyuan.replace('&&', '.*?')
            var yy = html.match(eval(yanyuan))
        } else { var yy = '' }
        if (proj_plot != '' && proj_plot != undefined) {
            var jianjie = "/" + toReg(proj_plot) + "/"
            log('正则简介：' + jianjie)
            jianjie.replace('&&', '.*?')
            var jj = html.match(eval(jianjie))
        } else { var jj = '' }
    }
    //显示详情
    dd(d, 'text_1', '类型：', lx)
    dd(d, 'text_1', '年代：', nd)
    dd(d, 'text_1', '地区：', dq)
    dd(d, 'text_1', '演员', yy)
    dd(d, 'text_1', '简介', jj)
    log('正则获取详情元素结束，且已经添加到组件组')
    //如果线路规则是空  
    var xlbiaotizhu = []
    if (tab_arr_rule != '' && tab_arr_rule != undefined) {
        var xllist = pdfa(html, tab_arr_rule)
        //线路列表数组
        xllist.forEach(it => {
            xlbiaotizhu.push(pdfh(it, tab_title))
        })
    }

    //播放列表数组
    var bflist = pdfa(html, list_arr_rule)
    //保存截取到的所有播放线路数据
    var bfzus = []
    var 补全选集列表规则 = list_arr_rule.split('&&').pop() + '&&'
    bflist.forEach(it => {
        let bfzu = []
        //epi_arr_rule 是一个标签，可能需要补全
        //一条线路的选集数据
        //epi_arr_rule 就一个标签 海阔中获取不到，需要补全
        let xjlist = pdfa(it, 补全选集列表规则 + epi_arr_rule)
        if (epi_is_jsoup === '1' || epi_is_jsoup === '是') {
            //jsoup写法 可以用PD系列函数
            for (let i = 0; i < xjlist.length; i++) {
                let jbiaoti = pdfh(xjlist[i], epi_title)
                //是否补全，没有判断，直接补
                let jlianjie = epiurl_prefix + pdfh(xjlist[i], epi_url) + epiurl_suffix
                //把标题和链接放在一起 保存大数组中 用#分隔
                bfzu.push(jbiaoti + '#' + jlianjie)
            }

        } else {
            //正则写法
            for (let i = 0; i < xjlist.length; i++) {
                let jbiaotireg = "/" + toReg(epi_title) + "/"
                jbiaotireg.replace('&&', '.*?')
                let jbiaoti = xjlist[i].match(eval(jbiaotireg))

                let jlianjiereg = "/" + toReg(epi_url) + "/"
                jlianjiereg.replace('&&', '.*?')
                //是否补全，没有判断，直接补
                let jlianjie = epiurl_prefix + xjlist[i].match(eval(jlianjiereg)) + epiurl_suffix
                //把标题和链接放在一起 保存大数组中 用#分隔
                bfzu.push(jbiaoti + '#' + jlianjie)
            }
        }
        if (epi_reverse === '0' || epi_reverse === '否') {
            bfzus.push(bfzu)
        } else {
            bfzu.reverse()
            bfzus.push(bfzu)
        }


    })
    if (xlbiaotizhu.length != bfzus.length) {
        log('注意：线路标题和线路数据不对应！')
        log('线路标题：')
        log(xlbiaotizhu)
        log('线路数据：')
        log(bfzus)
    }
    //根据线路标题添加数据
    if (xlbiaotizhu.length != 0) {
        //多条线路
        xlbiaotizhu.forEach((it, i) => {
            dd(d, 'icon_1_search', it)
            bfzus[i].forEach(itt => {
                let tt = itt.split('#')
                //不管原链接 在播放链接前加video
                dd(d, 't2', tt[0], '', '', playurl(tt[1]))
            })
        })
    } else {
        //就一条线路
        dd(d, 'icon_1_search', '只有一条线路')
        bfzus[0].forEach(itt => {
            let tt = itt.split('#')
            //不管原链接 在播放链接前加video
            dd(d, 't2', tt[0], '', '', playurl(tt[1]))
        })
    }
}

/**
 * playurl(url)  海阔小程序 播放链接添加
 * 功能说明： 1、http 开头 .m3u8 结尾  直接返回url。2、http开头 其他结尾 链接前加 video://。3、不以http开头  直接返回url 比如 magnet:? 磁力链接
 * 注意：个别网站链接会有错误，碰到再改
 * @param {String} url 链接地址 
 * @returns 修改后的链接地址
 */
function playurl(url) {
    if (url.startsWith('http')) {
        //http开头
        if (url.endsWith('.m3u8')) {
            // http 开头 .m3u8 结尾  直接返回
            return url
        } else if (url.indexOf('aliyundrive.com') != -1 || url.indexOf('baidu.com') != -1) {
            return url
        }
        else {
            //http开头 其他结尾 链接前加 video://
            return 'video://' + url
        }
    } else {
        // 不以http开头  直接返回url 比如 magnet:? 磁力链接
        //这个地方会有些错误  碰到再处理
        return url
    }

}

/**
 * 取筛选数据XYQH(f, surl)
 * @param {JSON} f 接口文件的json对象
 * @param {String} surl 要根据赛选结果修改的网络链接 
 * @returns 
 */
function 取筛选数据XYQH(f) {
    var data = {
        err: '',
        //栏目名数组 
        子类名: [],
        //栏目名对应的地址链接（补全后地址）
        子类链接: []
    }
    //如果筛选不为空
    let filterdata = f.filterdata || f.筛选数据
    //赛选数据=ext 就使用下面赛选
    if (filterdata === 'ext') {
        var curl = f.class_url || f.分类链接
        // 对应分类链接{cateId}，第一子分类1&第一子分类2||第二子分类1&第二子分类2
        //注意：{cateId} 和大类替换词是一样的，因为替换位置是一样的
        let fclass_name = f.fclass_name || f.筛选子分类名称
        let fclass_value = f.fclass_value || f.筛选子分类替换词
        let 点击序号 = parseInt(getMyVar('点击序号', '0'))
        let 子类组 = fclass_name.split('||')[点击序号]
        let 子类替换组 = fclass_value.split('||')[点击序号]
        data.子类名 = 子类组.split('&')
        //log(data.子类名)
        if (fclass_value.indexOf('＆＆') != -1) {
            var v = 子类替换组.split('＆＆')
        } else {
            var v = 子类替换组.split('&')
        }
        //log(v)
        var reg = '/{cateId}/g'
        for (let i = 0; i < v.length; i++) {
            //其他筛选以后写，先清理链接
            //log(curl)
            /*
            curl=curl.replace(/{by}/g,'')
            curl=curl.replace(/{lang}/g,'')
            curl=curl.replace(/{year}/g,'')
            curl=curl.replace(/{area}/g,'')
            curl=curl.replace(/{class}/g,'')
            */
            let cu = curl.replace(eval(reg), v[i])
            cu = clearurl(cu)
            data.子类链接.push(cu)
            /* 点击筛选再设置当前连接
            if(i==0){
                putMyVar('当前连接',cu)
                log('取筛选数据 设置当前连接：'+cu)
            }
            */
            //log(curl)
        }

        //log(data.子类链接)
        let fcatelog_name = f.fcatelog_name || f.筛选类型名称
        let fcatelog_value = f.fcatelog_value || f.筛选类型替换词
        let farea_name = f.farea_name || f.筛选地区名称
        let farea_value = f.farea_value || f.筛选地区替换词
        let fyear_name = f.fyear_name || f.筛选年份名称
        let fyear_value = f.fyear_value || f.筛选年份替换词
        let flang_name = f.flang_name || f.筛选语言名称
        let flang_value = f.flang_value || f.筛选语言替换词
        let fsort_name = f.fsort_name || f.筛选排序名称
        let fsort_value = f.fsort_value || f.筛选排序替换词
    } else {
        //无筛选数据
        log('接口文件未启用筛选！')
        data.err = 'err:接口文件未启用筛选！'
    }

    return data
}

function 显示筛选(data) {
    var d1 = []
    d1.push({ col_type: 'line' })
    log('进入显示筛选函数！')
    for (let i = 0; i < data.子类名.length; i++) {
        var b = $('#noLoading#').lazyRule((it) => {
            putMyVar('当前连接', it)
            log('显示筛选 设置当前连接：' + it)
            //putMyVar('点击序号',i+'')
            //动态添加不用刷新页面
            //MY_RULE.url=it
            //refreshPage()
            //必须返回一个链接，不然报错
            refreshPage()
            return 'toast://切换分类中'

        }, data.子类链接[i])

        d1.push({
            col_type: 'scroll_button',
            title: data.子类名[i],
            url: b
        })
    }
    return d1
}

/**
 * toReg(str) 将字符串转换成正则表达式 
 * @param {String} str 要转换的字符串 
 * @returns {String}
 */
function toReg(str) {
    //var RexStr = /\/|\\|\(|\)|\[|\]|\{|\}|\$|\*|\+|\.|\?|\^|\|/g
    //log('toreg 输入 str ：'+str)
    str = str.replace(/\//g, '\\\/')
    //str=str.replace(/\\/g,'\\\\')
    str = str.replace(/\(/g, '\\\(')
    str = str.replace(/\)/g, '\\\)')
    str = str.replace(/\[/g, '\\\[')
    str = str.replace(/\]/g, '\\\]')
    str = str.replace(/\}/g, '\\\}')
    str = str.replace(/\{/g, '\\\{')
    str = str.replace(/\$/g, '\\\$')
    str = str.replace(/\*/g, '\\\*')
    str = str.replace(/\./g, '\\\.')
    str = str.replace(/\?/g, '\\\?')
    str = str.replace(/\^/g, '\\\^')
    str = str.replace(/\|/g, '\\\|')
    str = str.replace(/\'/g, '\\\'')
    str = str.replace(/\"/g, '\\\"')
    log('toreg 得到正则表达式 ：' + str)
    /*
    str = str.replace(RexStr, function(MatchStr) {
        log('satchstr:'+MatchStr)
        switch (MatchStr) {
        case "/":
            return "\/";
            break;
        case '\\':
            return "\\";
            break;
        case "(":
            return "\(";
            break;
        case ")":
            return "\)";
            break;
        case "[":
            return "\[";
            break;
        case "]":
            return "\]";
            break;
        case '{':
            return "\{";
            break;
        case "}":
            return "\}";
            break;
        case "$":
            return "\$";
            break;
        case "*":
            return "\*";
            break;
        case "+":
            return "\+";
            break;
        case '.':
            return "\.";
            break;
        case "?":
            return "\?";
             break;
        case "^":
            return "\^";
            break;
        case "|":
            return "\|";
            break;
        default:
            break;
        }
    })
    */
    return str;
}

/**
 * clearurl(url) 清理url中的替换词 {cateId} fyclass 等
 * @param {*} url 
 */
function clearurl(url) {
    let reg = /{by}|{lang}|{year}|{area}|{class}/g
    return url.replace(eval(reg), '')
}


//模板Q中验证码使用

/*
while (/输入验证码|系统安全验证/.test(html)) {
    let headers = {
        "User-Agent": MOBILE_UA,
        "Referer": MY_URL
    }
    let ssyz = 'TloGnnikThrfs/5fDNlk5CSsbaGtAH7W/uMZjuYoIupB6bCoo9CotLQHfPIdGgbkbynKqL2aUE2Xy558X2QxHYtTU09vD+4oaCDIuSZO7nxDbLfRGfWj7zql+yMbvF+aJoD/m6Psfw/PyYOAp/ZVGdrPzaCByfd0HL5DFVSw+YF2OC40V8SP9RxdFKKdrBuPxCWdxUCFrJ+1lRy/TU3LC84C4xxEBhgud7RtBp0zZArqBE06+Z3JtDP0eFCz/D5X0409qPHK3e1y/LuUgccuxpHnjYLE1GjlP8wYA2hQWe7yPngggQBHw33/gvb3tuCcxEKTWgmah/R32AH9ZF8jF7WemT26lUizVXe/spCdhDgHR/zUhODD4PO6glI8JPhdu+VwfPyRLG2D7CUo1L6SIF+0fYf0oTOWN13UPITo5+uZd/WnQQLU8NYx/WFCThEnkbzln9YGt60fRxsH+8uMDFgaBiC+z2SpcxB9gZ6GXypLSXWaj+qEUbGJKEx+jK/v5fnrkIhCdwNbkp9dRks6dmlYlBifzoWF8RkuC3rqPtoScBkMOMZu7GiVtoHEdHUozmnUIdrU1LGIqq9WnG7X2a3yH8s65mjLuLnd3q0U8v+LMPnHL2/GjQuTQKVh+RKEPqK/JdrChGLNrjcHvLHDbHEshrGZuQOdEphbx/PkhkvaYy4K1MO84R17guRsKs/V6niUPaL+XbQ7c3fqJS4VHJwludJTDe02euffGCm0PJIPlAOgLHnX0izJhA6q738R2UwQcWBQjJt79aF+kyqSdyt1QPVQVjaC3IpRf7PgsDhEJ7bi9nSclyIzgJ9DCJ4T+8dG1xHhKyZasT7L/x9Lfr1Mgs8nBZER2W9ax7iTkNK+X5ACU//p/YoP/uAanDtb3D0iKUUuXFH+Jbb0x1P322S2w6BJ46nuNHBMHTpVuWwhZeZzriGh7qoOywLWiExBMKyxTGLnmKh7r03/yXKYWIJnpBN2MMycVHRZJ7RumHV4CIsVrq7iRP48823RJVt9OtyP7uuc3wBBV3kcZUzbbaYdWBx1+Au+Od2u7lR6joOL810mcJm/f7J5TvGQP6HGph1YHHX4C7453a7uVHqOgyjjh5EBd720MEBY23c+TKq/z9UpWDDOg48ZFnwSIhFqitWdiZiqsaYuN0/SXwiK8EG9eQ29u2XDJoDW4mlwtcRO7vaX5XcFsgf4/mLU07mi';
    evalPrivateJS(ssyz);

    let vcode = getVCode2(MY_HOME + '/index.php/verify/index.html?', JSON.stringify(headers), 'num');
    fetch(MY_HOME + html.match(/\/index.php.*?verify=/)[0] + JSON.parse(vcode).ret, {
        headers: headers,
        method: 'POST'
    })
    var yz = MY_TYPE == 'home' ? true_url : MY_URL
    log(MY_TYPE)
    html = request(yz, {
        //   headers: headers
    })
}
if (/频繁操作/.test(html)) {
    d.push({
    title: '网站搜索时间间隔',
    desc: "下拉重试"
    })
}
*/
//验证码相关  以后研究
/**
 * 
 * @param {*} url 
 * @param {*} html 
 * @param {*} d 
 * @returns 
 */
function check(url, html, d) {
    let reload = false;
    if (/验证码|系统安全验证/.test(html)) {
        let headers = {
            "User-Agent": MOBILE_UA,
            "Referer": url
        };
        MY_HOME = getHome(url);
        let ssyz = 'TloGnnikThrfs/5fDNlk5CSsbaGtAH7W/uMZjuYoIupB6bCoo9CotLQHfPIdGgbkbynKqL2aUE2Xy558X2QxHYtTU09vD+4oaCDIuSZO7nxDbLfRGfWj7zql+yMbvF+aJoD/m6Psfw/PyYOAp/ZVGdrPzaCByfd0HL5DFVSw+YF2OC40V8SP9RxdFKKdrBuPxCWdxUCFrJ+1lRy/TU3LC84C4xxEBhgud7RtBp0zZArqBE06+Z3JtDP0eFCz/D5X0409qPHK3e1y/LuUgccuxpHnjYLE1GjlP8wYA2hQWe7yPngggQBHw33/gvb3tuCcxEKTWgmah/R32AH9ZF8jF7WemT26lUizVXe/spCdhDgHR/zUhODD4PO6glI8JPhdu+VwfPyRLG2D7CUo1L6SIF+0fYf0oTOWN13UPITo5+uZd/WnQQLU8NYx/WFCThEnkbzln9YGt60fRxsH+8uMDFgaBiC+z2SpcxB9gZ6GXypLSXWaj+qEUbGJKEx+jK/v5fnrkIhCdwNbkp9dRks6dmlYlBifzoWF8RkuC3rqPtoScBkMOMZu7GiVtoHEdHUozmnUIdrU1LGIqq9WnG7X2a3yH8s65mjLuLnd3q0U8v+LMPnHL2/GjQuTQKVh+RKEPqK/JdrChGLNrjcHvLHDbHEshrGZuQOdEphbx/PkhkvaYy4K1MO84R17guRsKs/V6niUPaL+XbQ7c3fqJS4VHJwludJTDe02euffGCm0PJIPlAOgLHnX0izJhA6q738R2UwQcWBQjJt79aF+kyqSdyt1QPVQVjaC3IpRf7PgsDhEJ7bi9nSclyIzgJ9DCJ4T+8dG1xHhKyZasT7L/x9Lfr1Mgs8nBZER2W9ax7iTkNK+X5ACU//p/YoP/uAanDtb3D0iKUUuXFH+Jbb0x1P322S2w6BJ46nuNHBMHTpVuWwhZeZzriGh7qoOywLWiExBMKyxTGLnmKh7r03/yXKYWIJnpBN2MMycVHRZJ7RumHV4CIsVrq7iRP48823RJVt9OtyP7uuc3wBBV3kcZUzbbaYdWBx1+Au+Od2u7lR6joOL810mcJm/f7J5TvGQP6HGph1YHHX4C7453a7uVHqOgyjjh5EBd720MEBY23c+TKq/z9UpWDDOg48ZFnwSIhFqitWdiZiqsaYuN0/SXwiK8EG9eQ29u2XDJoDW4mlwtcRO7vaX5XcFsgf4/mLU07mi';
        evalPrivateJS(ssyz);

        let vcode = getVCode2(MY_HOME + '/index.php/verify/index.html?', JSON.stringify(headers), 'num');
        fetch(MY_HOME + html.match(/\/index.php.*?verify=/)[0] + JSON.parse(vcode).ret, {
            headers: headers,
            method: 'POST'
        });
        reload = true;
    }
    return reload;
}


function 获取ck(set) {
    var ckpath = 'hiker://files/cache/cookie.json';
    var oldck = fetch(ckpath) || '{}';
    //log('旧的cookie:'+oldck);
    oldck = JSON.parse(oldck);
    return oldck[set] || ''
}
function 注入验证码识别(id, set, extra) {
    // id=id||'.tncode';
    id = id || '';
    set = set || 'yzm_cookie';
    extra = extra || {};
    if (typeof (log) == "undefiend") {
        log = fy_bridge_app.log;
    }
    var js = $.toString((id, set, extra) => {
        eval(fy_bridge_app.getInternalJs());
        //fba.log('进入x5处理中');
        //fba.log(fba.getVar('dr依赖'));
        var ckpath = 'hiker://files/cache/cookie.json';
        function cookieSet() {
            // fba.log('自动cookie设置:' + set + '=>' + document.cookie);
            //JSON.stringify
            //JSON.parse
            var oldck = request(ckpath) || '{}';
            fba.log('旧的cookie:' + oldck);
            oldck = JSON.parse(oldck);
            oldck[set] = document.cookie;
            fba.putVar(set, document.cookie);
            var newCk = JSON.stringify(oldck);
            fba.writeFile(ckpath, newCk);
            fba.log('新的cookie:' + newCk);
        }
        if (id) { //填了id的话
            var btn = document.createElement('button');
            let css = extra.样式 || 'border-radius:20px;width:auto;height:20px;';
            btn.setAttribute('style', css);
            btn.setAttribute('id', 'btn1');
            let text = extra.文字 || '完成并返回重试';
            btn.innerText = text;
            btn.onclick = function () {
                try {
                    fba.log('手动点击cookie设置:' + set + '=>' + document.cookie);
                    cookieSet();
                    if (confirm('已设置当前页cookie，返回查看搜索结果。返回后需要手动下拉刷新！！！')) {
                        fba.parseLazyRule('hiker://empty@lazyRule=.js:back()');
                    }

                } catch (e) {
                    alert(e.message)
                }
            }
            var main = document.querySelector(id);
            main.appendChild(btn);
        } else {//没填就自动注入，刷新都算
            if (document.cookie) {//如果有cookie
                try {
                    fba.log('自动cookie设置:' + set + '=>' + document.cookie);
                    cookieSet();
                } catch (e) {
                    alert(e.message)
                }
            }
        }
    }, id, set, extra);
    return js
}

function 道长验证码(title, myurl, id, set, extra) {

    if (getVar(set, '') && !getMyVar('cookie')) {
        putMyVar('cookie', getVar(set, ''));
        refreshPage(true);
        return;
    }

    //必填链接，id，cookie名称
    extra = extra || false;
    title = title || '网站触发了人机验证，点此处理';
    /*
    var url=$().lazyRule((title,MY_URL,id,set,extra,注入验证码识别)=>{
    if(getVar(set,'')&&!getMyVar('cookie')){
    putMyVar('cookie',getVar(set,''));
    refreshPage(true);
    return'hiker://empty';
    }
    return $(MY_URL).rule((注入验证码识别,id,set,extra)=>{
                //log(typeof(注入验证码识别))
                let d=[];
                d.push({
                 col_type: "x5_webview_single",
                 url: MY_URL,
                 desc: "float&&100%",
                 extra: {
                   canBack: true,
                   js:注入验证码识别(id,set,extra)
                  }});
                setResult(d);
          },注入验证码识别,id,set,extra);

    },title,MY_URL,id,set,extra,注入验证码识别);
    */
    //log('待注入:'+MY_URL);
    var url = $(myurl).rule((注入验证码识别, id, set, extra) => {
        //log(typeof(注入验证码识别))
        input = MY_URL;
        require(getVar('dr依赖'));
        //log('注入了:'+MY_URL);
        var oldck = 获取ck(set);
        setPageTitle('道长验证码通杀');
        addListener('onClose', $.toString((set, oldck, 获取ck) => {
            // refreshPage(false); //返回自动刷新使设置生效
            log('退出了通杀界面,旧的cookie为:' + oldck);
            let newck = 获取ck(set);
            log('新的cookie为:' + newck);
            if (!newck) {
                let error = '未获取cookie，验证失败！';
                log(error);
                //setError(error);
                //throw error;
            } else if (oldck === newck) {
                log('cookie未更新，验证可能未通过');
            }
        }, set, oldck, 获取ck));
        let d = [];
        d.push({
            col_type: "x5_webview_single",
            url: input,
            desc: "float&&100%",
            extra: {
                canBack: true,
                js: 注入验证码识别(id, set, extra)
            }
        });
        setResult(d);
    }, 注入验证码识别, id, set, extra);
    let d = [];
    d.push({
        title: title,
        col_type: 'text_1',
        url: url,
    });
    setResult(d);
    // $().b64().rule()  可以实现在lazyRule里返回rule
}

//返回一个对象数组 对应各种模板的默认值
//使用道长js的模板
function getjsMubans() {
    var mubanDict = { // 模板字典
        mxpro: {
            title: '',
            host: '',
            // homeUrl:'/',
            url: '/vodshow/fyclass--------fypage---.html',
            searchUrl: '/vodsearch/**----------fypage---.html',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {//网站的请求头,完整支持所有的,常带ua和cookies
                'User-Agent': 'MOBILE_UA',
                // "Cookie": "searchneed=ok"
            },
            class_parse: '.navbar-items li:gt(2):lt(8);a&&Text;a&&href;/(\\d+).html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: '.tab-list.active;a.module-poster-item.module-item;.module-poster-item-title&&Text;.lazyload&&data-original;.module-item-note&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: 'body a.module-poster-item.module-item;a&&title;.lazyload&&data-original;.module-item-note&&Text;a&&href',
            二级: {
                "title": "h1&&Text;.module-info-tag&&Text",
                "img": ".lazyload&&data-original",
                "desc": ".module-info-item:eq(1)&&Text;.module-info-item:eq(2)&&Text;.module-info-item:eq(3)&&Text",
                "content": ".module-info-introduction&&Text",
                "tabs": ".module-tab-item",
                "lists": ".module-play-list:eq(#id) a"
            },
            搜索: 'body .module-item;.module-card-item-title&&Text;.lazyload&&data-original;.module-item-note&&Text;a&&href;.module-info-item-content&&Text',
        },
        mxone5: {
            title: '',
            host: '',
            url: '/show/fyclass--------fypage---.html',
            searchUrl: '/search/**----------fypage---.html',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            class_parse: '.nav-menu-items&&li;a&&Text;a&&href;.*/(.*?).html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: '.module-list;.module-items&&.module-item;a&&title;img&&data-src;.module-item-text&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: '.module-items .module-item;a&&title;img&&data-src;.module-item-text&&Text;a&&href',
            二级: {
                "title": "h1&&Text;.tag-link&&Text",
                "img": ".module-item-pic&&img&&data-src",
                "desc": ".video-info-items:eq(0)&&Text;.video-info-items:eq(1)&&Text;.video-info-items:eq(2)&&Text;.video-info-items:eq(3)&&Text",
                "content": ".vod_content&&Text",
                "tabs": ".module-tab-item",
                "lists": ".module-player-list:eq(#id)&&.scroll-content&&a"
            },
            搜索: '.module-items .module-search-item;a&&title;img&&data-src;.video-serial&&Text;a&&href',
        },
        首图: {
            title: '',
            host: '',
            url: '/vodshow/fyclass--------fypage---/',
            searchUrl: '/vodsearch/**----------fypage---.html',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {//网站的请求头,完整支持所有的,常带ua和cookies
                'User-Agent': 'MOBILE_UA',
                // "Cookie": "searchneed=ok"
            },
            class_parse: '.myui-header__menu li.hidden-sm:gt(0):lt(5);a&&Text;a&&href;/(\\d+).html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: 'ul.myui-vodlist.clearfix;li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: '.myui-vodlist li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
            二级: {
                "title": ".myui-content__detail .title&&Text;.myui-content__detail p:eq(-2)&&Text",
                "img": ".myui-content__thumb .lazyload&&data-original",
                "desc": ".myui-content__detail p:eq(0)&&Text;.myui-content__detail p:eq(1)&&Text;.myui-content__detail p:eq(2)&&Text",
                "content": ".content&&Text",
                "tabs": ".nav-tabs:eq(0) li",
                "lists": ".myui-content__list:eq(#id) li"
            },
            搜索: '#searchList li;a&&title;.lazyload&&data-original;.text-muted&&Text;a&&href;.text-muted:eq(-1)&&Text',
        },
        首图2: {
            title: '',
            host: '',
            url: '/list/fyclass-fypage.html',
            searchUrl: '/vodsearch/**----------fypage---.html',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {
                'User-Agent': 'UC_UA',
                // "Cookie": ""
            },
            // class_parse:'.stui-header__menu li:gt(0):lt(7);a&&Text;a&&href;/(\\d+).html',
            class_parse: '.stui-header__menu li:gt(0):lt(7);a&&Text;a&&href;.*/(.*?).html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: 'ul.stui-vodlist.clearfix;li;a&&title;.lazyload&&data-original;.pic-text&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: '.stui-vodlist li;a&&title;a&&data-original;.pic-text&&Text;a&&href',
            二级: {
                "title": ".stui-content__detail .title&&Text;.stui-content__detail p:eq(-2)&&Text",
                "img": ".stui-content__thumb .lazyload&&data-original",
                "desc": ".stui-content__detail p:eq(0)&&Text;.stui-content__detail p:eq(1)&&Text;.stui-content__detail p:eq(2)&&Text",
                "content": ".detail&&Text",
                "tabs": ".stui-vodlist__head h3",
                "lists": ".stui-content__playlist:eq(#id) li"
            },
            搜索: 'ul.stui-vodlist__media:eq(0) li,ul.stui-vodlist:eq(0) li,#searchList li;a&&title;.lazyload&&data-original;.text-muted&&Text;a&&href;.text-muted:eq(-1)&&Text',
            搜索1: 'ul.stui-vodlist&&li;a&&title;.lazyload&&data-original;.text-muted&&Text;a&&href;.text-muted:eq(-1)&&Text',
            搜索2: 'ul.stui-vodlist__media&&li;a&&title;.lazyload&&data-original;.text-muted&&Text;a&&href;.text-muted:eq(-1)&&Text',
        },
        默认: {
            title: '',
            host: '',
            url: '/vodshow/fyclass--------fypage---.html',
            searchUrl: '/vodsearch/-------------.html?wd=**',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {
                'User-Agent': 'MOBILE_UA',
            },
            play_parse: true,
            lazy: '',
            limit: 6,
            double: true, // 推荐内容是否双层定位
        },
        vfed: {
            title: '',
            host: '',
            url: '/index.php/vod/show/id/fyclass/page/fypage.html',
            searchUrl: '/index.php/vod/search/page/fypage/wd/**.html',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {
                'User-Agent': 'UC_UA',
            },
            // class_parse:'.fed-pops-navbar&&ul.fed-part-rows&&a.fed-part-eone:gt(0):lt(5);a&&Text;a&&href;.*/(.*?).html',
            class_parse: '.fed-pops-navbar&&ul.fed-part-rows&&a;a&&Text;a&&href;.*/(.*?).html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: 'ul.fed-list-info.fed-part-rows;li;a.fed-list-title&&Text;a&&data-original;.fed-list-remarks&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: '.fed-list-info&&li;a.fed-list-title&&Text;a&&data-original;.fed-list-remarks&&Text;a&&href',
            二级: {
                "title": "h1.fed-part-eone&&Text;.fed-deta-content&&.fed-part-rows&&li&&Text",
                "img": ".fed-list-info&&a&&data-original",
                "desc": ".fed-deta-content&&.fed-part-rows&&li:eq(1)&&Text;.fed-deta-content&&.fed-part-rows&&li:eq(2)&&Text;.fed-deta-content&&.fed-part-rows&&li:eq(3)&&Text",
                "content": ".fed-part-esan&&Text",
                "tabs": ".fed-drop-boxs&&.fed-part-rows&&li",
                "lists": ".fed-play-item:eq(#id)&&ul:eq(1)&&li"
            },
            搜索: '.fed-deta-info;h1&&Text;.lazyload&&data-original;.fed-list-remarks&&Text;a&&href;.fed-deta-content&&Text',
        },
        海螺3: {
            title: '',
            host: '',
            searchUrl: '/v_search/**----------fypage---.html',
            url: '/vod_____show/fyclass--------fypage---.html',
            headers: {
                'User-Agent': 'MOBILE_UA'
            },
            timeout: 5000,
            class_parse: 'body&&.hl-nav li:gt(0);a&&Text;a&&href;.*/(.*?).html',
            cate_exclude: '明星|专题|最新|排行',
            limit: 40,
            play_parse: true,
            lazy: '',
            推荐: '.hl-vod-list;li;a&&title;a&&data-original;.remarks&&Text;a&&href',
            double: true,
            一级: '.hl-vod-list&&.hl-list-item;a&&title;a&&data-original;.remarks&&Text;a&&href',
            二级: {
                "title": ".hl-infos-title&&Text;.hl-text-conch&&Text",
                "img": ".hl-lazy&&data-original",
                "desc": ".hl-infos-content&&.hl-text-conch&&Text",
                "content": ".hl-content-text&&Text",
                "tabs": ".hl-tabs&&a",
                "lists": ".hl-plays-list:eq(#id)&&li"
            },
            搜索: '.hl-list-item;a&&title;a&&data-original;.remarks&&Text;a&&href',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
        },
        海螺2: {
            title: '',
            host: '',
            searchUrl: '/index.php/vod/search/page/fypage/wd/**/',
            url: '/index.php/vod/show/id/fyclass/page/fypage/',
            headers: {
                'User-Agent': 'MOBILE_UA'
            },
            timeout: 5000,
            class_parse: '#nav-bar li;a&&Text;a&&href;id/(.*?)/',
            limit: 40,
            play_parse: true,
            lazy: '',
            推荐: '.list-a.size;li;a&&title;.lazy&&data-original;.bt&&Text;a&&href',
            double: true,
            一级: '.list-a&&li;a&&title;.lazy&&data-original;.list-remarks&&Text;a&&href',
            二级: {
                "title": "h2&&Text;.deployment&&Text",
                "img": ".lazy&&data-original",
                "desc": ".deployment&&Text",
                "content": ".ec-show&&Text",
                "tabs": "#tag&&a",
                "lists": ".play_list_box:eq(#id)&&li"
            },
            搜索: '.search-list;a&&title;.lazy&&data-original;.deployment&&Text;a&&href',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
        },
        短视: {
            title: '',
            host: '',
            // homeUrl:'/',
            url: '/channel/fyclass-fypage.html',
            searchUrl: '/search.html?wd=**',
            searchable: 2,//是否启用全局搜索,
            quickSearch: 0,//是否启用快速搜索,
            filterable: 0,//是否启用分类筛选,
            headers: {//网站的请求头,完整支持所有的,常带ua和cookies
                'User-Agent': 'MOBILE_UA',
                // "Cookie": "searchneed=ok"
            },
            class_parse: '.menu_bottom ul li;a&&Text;a&&href;.*/(.*?).html',
            cate_exclude: '解析|动态',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: '.indexShowBox;ul&&li;a&&title;img&&data-src;.s1&&Text;a&&href',
            double: true, // 推荐内容是否双层定位
            一级: '.pic-list&&li;a&&title;img&&data-src;.s1&&Text;a&&href',
            二级: {
                "title": "h1&&Text;.content-rt&&p:eq(0)&&Text",
                "img": ".img&&img&&data-src",
                "desc": ".content-rt&&p:eq(1)&&Text;.content-rt&&p:eq(2)&&Text;.content-rt&&p:eq(3)&&Text;.content-rt&&p:eq(4)&&Text;.content-rt&&p:eq(5)&&Text",
                "content": ".zkjj_a&&Text",
                "tabs": ".py-tabs&&option",
                "lists": ".player:eq(#id) li"
            },
            搜索: '.sr_lists&&ul&&li;h3&&Text;img&&data-src;.int&&p:eq(0)&&Text;a&&href',
        },
        短视2: {
            title: '',
            host: '',
            class_name: '电影&电视剧&综艺&动漫',
            class_url: '1&2&3&4',
            searchUrl: '/index.php/ajax/suggest?mid=1&wd=**&limit=50',
            searchable: 2,
            quickSearch: 0,
            headers: { 'User-Agent': 'MOBILE_UA' },
            url: '/index.php/api/vod#type=fyclass&page=fypage',
            filterable: 0,//是否启用分类筛选,
            filter_url: '',
            filter: {},
            filter_def: {},
            detailUrl: '/index.php/vod/detail/id/fyid.html',
            play_parse: true,
            lazy: '',
            limit: 6,
            推荐: '.list-vod.flex .public-list-box;a&&title;.lazy&&data-original;.public-list-prb&&Text;a&&href',
            一级: 'js:let body=input.split("#")[1];let t=Math.round(new Date/1e3).toString();let key=md5("DS"+t+"DCC147D11943AF75");let url=input.split("#")[0];body=body+"&time="+t+"&key="+key;print(body);fetch_params.body=body;let html=post(url,fetch_params);let data=JSON.parse(html);VODS=data.list.map(function(it){it.vod_pic=urljoin2(input.split("/i")[0],it.vod_pic);return it});',
            二级: {
                "title": ".slide-info-title&&Text;.slide-info:eq(3)--strong&&Text",
                "img": ".detail-pic&&data-original",
                "desc": ".fraction&&Text;.slide-info-remarks:eq(1)&&Text;.slide-info-remarks:eq(2)&&Text;.slide-info:eq(2)--strong&&Text;.slide-info:eq(1)--strong&&Text",
                "content": "#height_limit&&Text",
                "tabs": ".anthology.wow.fadeInUp.animated&&.swiper-wrapper&&a",
                "tab_text": ".swiper-slide&&Text",
                "lists": ".anthology-list-box:eq(#id) li"
            },
            搜索: 'json:list;name;pic;;id',
        }
    };
    return JSON.parse(JSON.stringify(mubanDict));
}

